Aller au contenu principal
Version : 29.7

Tester des Applications React Native

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

Get a deeper insight into testing a working React Native app example by reading the following series: Part 1: Jest – Snapshot come into play and Part 2: Jest – Redux Snapshots for your Actions and Reducers.

Configuration

Starting from react-native version 0.38, a Jest setup is included by default when running react-native init. La configuration suivante devrait être automatiquement ajoutée à votre fichier package.json :

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

Run yarn test to run tests with Jest.

astuce

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.

Test Snapshot

Let's create a snapshot test for a small intro component with a few views and text components and some styles:

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;

Utilisons maintenant le moteur de rendu de React and la fonctionnalité de snapshot de Jest pour capturer le rendu du composant dans un fichier:

__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();
});

When you run yarn test or jest, this will produce an output file like this:

__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>
`;

La prochaine fois que vous exécuterez les tests, la sortie rendue sera comparée au snapshot précédemment créé. Le snapshot doit être committé avec les changements de code. Lorsqu'un test de snapshot échoue, vous devez vérifier s'il s'agit d'un changement intentionnel ou non intentionnel. If the change is expected you can invoke Jest with jest -u to overwrite the existing snapshot.

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

Configuration prédéfinie

Le préréglage définit l'environnement et il est très subjectif et basé sur ce que nous avons trouvé d'utile sur Facebook. Toutes les options de configuration peuvent être écrasées tout comme elles peuvent être personnalisées si aucun préréglage n'est utilisé.

Environnement

react-native ships with a Jest preset, so the jest.preset field of your package.json should point to react-native. Le preset est un environnement node qui imite l'environnement d'une application React Native. Parce qu'il ne charge pas d'API DOM ou de navigateur, cela améliore grandement le temps de démarrage de Jest.

Personnalisation 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)/)"]
}

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. Le découpage en plusieurs patterns pourrait donc avoir des résultats inattendus si vous ne faites pas attention. 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/)"] // pas ce que vous voulez
}

setupFiles

If you'd like to provide additional configuration for every test file, the setupFiles configuration option can be used to specify setup scripts.

moduleNameMapper

The moduleNameMapper can be used to map a module path to a different module. Par défaut, le preset fait correspondre toutes les images à un module de base d'image, mais si un module ne peut être trouvé, cette option de configuration peut aider :

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

Astuces

Simuler des modules natifs en utilisant jest.mock

The Jest preset built into react-native comes with a few default mocks that are applied on a react-native repository. Cependant, certains composants ou composants tiers reposent sur du code natif pour être rendus. Dans de tels cas, le système de simulation manuelle de Jest peut aider à déchiffrer l'implémentation sous-jacente.

For example, if your code depends on a third party native video component called react-native-video you might want to stub it out with a manual mock like this:

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

This will render the component as <Video {...props} /> with all of its props in the snapshot output. See also caveats around Enzyme and React 16.

Parfois, vous devez fournir une simulation manuelle plus complexe. Par exemple, si vous souhaitez transférer les types de prop ou les champs statiques d'un composant natif vers une simulation, vous pouvez retourner un composant React différent d'une simulation à travers cette fonction d'aide de jest-react-native :

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

Ou si vous souhaitez créer votre propre simulation manuelle, vous pouvez faire quelque chose comme ceci :

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;
});

Dans d'autres cas, vous pouvez souhaiter simuler un module natif qui n'est pas un composant React. La même technique peut être appliquée. Nous recommandons d'inspecter le code source du module natif et de journaliser le module lors de l'exécution d'une application react native sur un appareil bien réel, puis de modéliser une simulation manuelle d'après le module réel.

If you end up mocking the same modules over and over it is recommended to define these mocks in a separate file and add it to the list of setupFiles.