Skip to main content
Versão: Próximo

Testando Apps React Native

At Facebook, we use Jest to test React Native applications.

Obtenha uma visão mais profunda em como testar um app React Native de exemplo lendo a seguinte série: Parte 1: Jest – Snapshot entra em jogo (em inglês) e Parte 2: Jest – Snapshots Redux para suas Actions e Reducers (em inglês).

Instalação

A partir da versão 0.38 de react-native, uma instalação Jest é incluída por padrão, ao executar react-native init. A seguinte configuração deve ser automaticamente adicionada ao seu arquivo package.json:

{
"scripts": {
"test": "jest"
},
"jest": {
"preset": "react-native"
}
}

Run yarn test to run tests with Jest.

tip

If you are upgrading your react-native application and previously used the jest-react-native preset, remove the dependency from your package.json file and change the preset to react-native instead.

Teste Snapshot

Vamos criar um teste snapshot para um pequeno componente "intro" com alguns "views" e componentes de texto e alguns estilos:

Intro.js
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';

class Intro extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>
This is a React Native snapshot test.
</Text>
</View>
);
}
}

const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex: 1,
justifyContent: 'center',
},
instructions: {
color: '#333333',
marginBottom: 5,
textAlign: 'center',
},
welcome: {
fontSize: 20,
margin: 10,
textAlign: 'center',
},
});

export default Intro;

Agora vamos usar o renderizador de teste do React e o recurso de snapshot do Jest para interagir com o componente e capturar a saída renderizada e criar um arquivo de snapshot:

__tests__/Intro-test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Intro from '../Intro';

test('renders correctly', () => {
const tree = renderer.create(<Intro />).toJSON();
expect(tree).toMatchSnapshot();
});

Ao executar yarn test ou jest, será produzido um arquivo de saída como a seguir:

__tests__/__snapshots__/Intro-test.js.snap
exports[`Intro renders correctly 1`] = `
<View
style={
Object {
"alignItems": "center",
"backgroundColor": "#F5FCFF",
"flex": 1,
"justifyContent": "center",
}
}>
<Text
style={
Object {
"fontSize": 20,
"margin": 10,
"textAlign": "center",
}
}>
Welcome to React Native!
</Text>
<Text
style={
Object {
"color": "#333333",
"marginBottom": 5,
"textAlign": "center",
}
}>
This is a React Native snapshot test.
</Text>
</View>
`;

Da próxima vez que você executar os testes, a saída renderizada será comparada ao snapshot criado anteriormente. O snapshot deve ser comitado junto às alterações de código. Quando um teste de snapshot falhar, é preciso inspecionar se trata-se de uma mudança pretendida ou não intencional. Se a mudança é esperada, pode-se invocar Jest com jest -u para substituir o snapshot existente.

The code for this example is available at examples/react-native.

Configuração predefinida

A predefinição configura o ambiente e é muito opinativa e baseada no que tem se mostrado ser útil no Facebook. Todas as opções de configuração podem ser substituídas assim como eles podem ser personalizados quando nenhuma predefinição é usada.

Ambiente

react-native vem com uma pré-definição Jest, então o campo jest.preset de seu package.json deve apontar para react-native. A predefinição é um ambiente node que imita o ambiente de um app React Native. Porque ele não carrega nenhum DOM ou APIs de navegador, melhora consideravelmente o tempo de inicialização do Jest.

personalização de transformIgnorePatterns

The transformIgnorePatterns option can be used to specify which files shall be transformed by Babel. Many react-native npm modules unfortunately don't pre-compile their source code before publishing.

By default the jest-react-native preset only processes the project's own source files and react-native. If you have npm dependencies that have to be transformed you can customize this configuration option by including modules other than react-native by grouping them and separating them with the | operator:

{
"transformIgnorePatterns": [
"node_modules/(?!(react-native|my-project|react-native-button)/)"
]
}

You can test which paths would match (and thus be excluded from transformation) with a tool like this.

transformIgnorePatterns will exclude a file from transformation if the path matches against any pattern provided. Splitting into multiple patterns could therefore have unintended results if you are not careful. In the example below, the exclusion (also known as a negative lookahead assertion) for foo and bar cancel each other out:

{
"transformIgnorePatterns": ["node_modules/(?!foo/)", "node_modules/(?!bar/)"] // not what you want
}

setupFiles

Se você gostaria de fornecer configuração adicional para cada arquivo de teste, a opção de configuração setupFiles pode ser usada para especificar os scripts de instalação.

moduleNameMapper

O moduleNameMapper pode ser usado para mapear um caminho de módulo para um módulo diferente. Por padrão a predefinição mapeia todas as imagens para um módulo de esboço de imagem, mas se um módulo não pode ser encontrado esta opção de configuração pode ajudar:

{
"moduleNameMapper": {
"my-module.js": "<rootDir>/path/to/my-module.js"
}
}

Dicas

Simule (mock, em inglês) módulos nativos usando jest.mock

A predefinição Jest interna do react-native vem com algumas simulações (mocks, em inglês) padrão que são aplicadas em um repositório react-native. However, some react-native components or third party components rely on native code to be rendered. Em tais casos, o sistema manual de simulação do Jest pode ajudar a simular a implementação subjacente.

Por exemplo, se seu código depende de um componente de vídeo nativo de terceiros chamado react-native-video convém esboçar ele com um simulação manual como esta:

jest.mock('react-native-video', () => 'Video');

Isto irá renderizar o componente como <Video {...props} /> com todas as suas propriedades no snapshot de saída. See also caveats around Enzyme and React 16.

Às vezes você precisa fornecer uma simulação manual mais complexa. Por exemplo, se você gostaria de transmitir os tipos das propriedades ou campos estáticos de um componente nativo para uma simulação (mock, em inglês), você pode retornar um componente React diferente a partir de uma simulação através deste auxiliar do jest-react-native:

jest.mock('path/to/MyNativeComponent', () => {
const mockComponent = require('react-native/jest/mockComponent');
return mockComponent('path/to/MyNativeComponent');
});

Ou se você gostaria de criar sua própria simulação manual, você pode fazer algo parecido com isto:

jest.mock('Text', () => {
const RealComponent = jest.requireActual('Text');
const React = require('react');
class Text extends React.Component {
render() {
return React.createElement('Text', this.props, this.props.children);
}
}
Text.propTypes = RealComponent.propTypes;
return Text;
});

Em outros casos, você pode querer simular um módulo nativo que não seja um componente React. A mesma técnica pode ser aplicada. Nós recomendamos inspecionar o código-fonte do módulo nativo e registrar o módulo ao executar um aplicativo react native em um dispositivo real e então modelar uma simulação manual após o módulo real.

Se você acabar por simular os mesmos módulos repetidamente vez após vez é recomendável definir estas simulações em um arquivo separado e adicioná-lo à lista de setupFiles.