Testes e performance no React Native com Expo
Configure Jest e Testing Library no Expo SDK 57, teste comportamento acessível e investigue performance React Native sem medir o modo dev.
Teste de componente confirma um comportamento observável; investigação de
performance mede o app no cenário próximo de produção. Nesta lição, você
configura Jest com jest-expo, testa um cartão pela acessibilidade e usa uma
sequência de diagnóstico antes de aplicar otimizações aleatórias.
Os exemplos continuam o componente da lição de componentes e estilos
e a FlatList de listas e navegação.
Não é necessário publicar o app para rodar testes unitários, mas medir apenas o
servidor de desenvolvimento produz conclusões enganosas.
Ensaio e cronômetro respondem perguntas diferentes
Imagine um teatro. O ensaio verifica se o ator entra na hora, diz a fala e reage ao sinal correto. O cronômetro mede quanto a troca de cenário demora sob as condições da apresentação. Um não substitui o outro.
No mapa técnico, Jest e Testing Library fazem o teste de comportamento; o profiler, os indicadores de frames e uma build release ajudam a medir performance. Um teste verde não prova 60 ou 120 quadros por segundo, e uma tela fluida não prova que a validação rejeita entrada vazia.
O limite da analogia é que alguns problemas atravessam as duas áreas: uma renderização em excesso pode tornar o teste lento e a tela travada. Mesmo assim, tecnicamente você precisa formular a pergunta: “a callback recebeu o id?” é teste; “qual commit demora mais?” é medição.
Instale versões compatíveis com Expo SDK 57
Use o resolvedor do SDK:
npx expo install jest-expo jest @types/jest \
@testing-library/react-native -- --save-devNo projeto executado, a matriz ficou em Jest 29.7.0, jest-expo 57.0.4 e
Testing Library 14.0.1. A documentação atual não recomenda
react-test-renderer: ele está depreciado e não combina com React 19 para este
fluxo.
Adicione scripts ao package.json:
{
"scripts": {
"test": "jest",
"typecheck": "tsc --noEmit"
}
}Typecheck e Jest têm trabalhos diferentes. O primeiro confere contratos estáticos; o segundo executa caminhos e expectativas. Rode os dois na revisão.
Configure o preset que entende React Native
Crie jest.config.js:
module.exports = {
preset: 'jest-expo',
testMatch: ['**/__tests__/**/*-test.[jt]s?(x)'],
};jest-expo prepara transformações e mocks compatíveis com módulos Expo e React
Native. Isso não simula perfeitamente Android ou iOS; cria um ambiente JavaScript
controlado para lógica e árvore de componentes. No Testing Library 14, os
matchers são registrados ao importar a biblioteca; o antigo caminho
@testing-library/react-native/extend-expect não existe nessa versão.
Se uma biblioteca nativa não tem implementação Jest, use o mock recomendado
por ela ou crie uma fronteira sua. Não substitua o módulo inteiro por
jest.fn() sem preservar o comportamento que o componente realmente usa.
Teste a interface pela porta que a pessoa usa
O cartão oferece papel de checkbox, nome e estado. Teste esse contrato:
import { fireEvent, render, screen } from '@testing-library/react-native';
import { HabitCard } from '@/components/habit-card';
test('alterna o hábito pelo controle acessível', () => {
const onToggle = jest.fn();
render(
<HabitCard
habit={{ id: 'agua', title: 'Beber água', done: false }}
onToggle={onToggle}
/>,
);
const checkbox = screen.getByRole('checkbox', {
name: /beber água, pendente/i,
});
fireEvent.press(checkbox);
expect(onToggle).toHaveBeenCalledTimes(1);
expect(onToggle).toHaveBeenCalledWith('agua');
});Buscar pelo papel acessível aproxima teste e experiência assistiva. Um seletor por nome de componente ou posição na árvore quebra numa refatoração que não mudou nada para o usuário.
Rode em modo de integração contínua:
npm test -- --ciA suíte editorial completa produziu:
Nenhum aparelho foi aberto nessa prova. Ela cobre reducer, componente, storage mockado e serviço HTTP injetado; navegação nativa, gestos e aparência ainda pedem testes em simulador ou dispositivo.
Reproduza uma expectativa errada e leia o diagnóstico
Troque temporariamente o id esperado:
- expect(onToggle).toHaveBeenCalledWith('agua');
+ expect(onToggle).toHaveBeenCalledWith('leitura');Jest mostra a diferença entre esperado e recebido:
O erro não diz automaticamente se o componente ou o teste está errado. Volte
ao requisito: pressionar “Beber água” deve emitir o id agua. Nesse caso, a
expectativa alterada é que mentiu; restaure-a. Teste não merece vitória sobre a
regra de negócio apenas porque está vermelho.
Meça fora do modo de desenvolvimento
O modo dev inclui avisos, ferramentas, verificações e Fast Refresh. Gere uma variante próxima de produção antes de comparar fluidez. Para Android local com ambiente configurado:
npx expo run:android --variant releasePara inspecionar apenas se os bundles resolvem, a prova desta série usou:
npx expo export --platform all --output-dir dist-proofA exportação passou para Android, iOS e web, mas não é benchmark. Tempo de build e tamanho do bundle não medem automaticamente frames da interação. Defina um cenário, dispositivo, quantidade de itens e métrica antes de afirmar ganho.
Use as ferramentas de desenvolvimento do React Native para localizar commits de renderização e indicadores de JS/UI frames quando apropriado. Em React Native 0.86, recursos de performance global também ajudam a coletar medidas do runtime, mas o resultado precisa de contexto reproduzível.
Trate FlatList a partir do gargalo observado
Comece com identidade estável e componentes baratos:
const renderHabit = useCallback(
({ item }: { item: Habit }) => (
<HabitCard habit={item} onToggle={toggleHabit} />
),
[toggleHabit],
);
<FlatList
data={habits}
initialNumToRender={10}
keyExtractor={(habit) => habit.id}
renderItem={renderHabit}
windowSize={7}
/>;initialNumToRender equilibra primeira pintura e preenchimento da tela;
windowSize equilibra memória e risco de áreas vazias durante rolagem. Não
copie esses números como receita universal. Altura do item, aparelho e padrão
de rolagem mudam a decisão.
Se os itens têm altura fixa, getItemLayout pode evitar medição:
const ITEM_HEIGHT = 76;
<FlatList
data={habits}
getItemLayout={(_, index) => ({
index,
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
})}
keyExtractor={(habit) => habit.id}
renderItem={renderHabit}
/>;Inclua margens e separadores no cálculo. Declarar 76 quando o item varia com texto grande gera saltos e posicionamento incorreto. A otimização só é válida quando a premissa de altura fixa também é válida.
Evite memoização por reflexo
memo, useMemo e useCallback têm custo e dependências. Primeiro confirme
que o filho renderiza com props equivalentes e que esse trabalho pesa no cenário
medido. Depois estabilize callbacks e estruturas onde o profiler aponta valor.
Uma função recriada não é automaticamente um problema. React ainda precisa comparar dependências, e um callback memoizado que fecha sobre estado errado pode introduzir bug. Otimização é uma hipótese seguida de medida, não um ritual para deixar o arquivo com aparência avançada.
Missão: construa uma matriz de confiança
Adicione um teste para entrada vazia, um para falha HTTP e um para a ação do cartão. Depois rode a lista com 20, 200 e 2.000 itens numa build release e anote dispositivo, duração do cenário e sintoma antes de mudar configurações.
Camada Pergunta Prova
reducer ação gera o próximo estado? Jest
componente pessoa consegue acionar? Testing Library
navegação rota abre e volta? teste no app
performance rolagem perde frames onde? profiler + releaseAo terminar, você terá evidência separada por pergunta. O tutorial do app completo reúne essa estrutura, storage, API e Router num projeto executável.
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Node 24.16.0, Expo SDK 57.0.15, React Native 0.86.2, React 19.2.3, Jest 29.7.0, jest-expo 57.0.4 e Testing Library 14.0.1, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- Expo — Unit testing with Jest — docs.expo.dev
- Expo Router — Testing — docs.expo.dev
- React Native — Performance overview — reactnative.dev
- React Native — Optimizing FlatList Configuration — reactnative.dev


