Skip to main content
Version: 29.7

Testarea aplicațiilor 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.

Instalare

Starting from react-native version 0.38, a Jest setup is included by default when running react-native init. Urmatoarea configuratie ar trebui să fie adăugată automat în fişierul 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.

Testarea de imagine

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;

Acum haideţi să utilizăm procesorul de randare React şi funcționalitatea din Jest pentru testarea de imagine pentru a interacţiona cu componenta şi a captura rezultatul şi a crea un fişier de imagine:

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

Data viitoare când executaţi testele, rezultatul va fi comparat cu imaginea creată anterior. The snapshot should be committed along with code changes. Atunci când un test de imagine eșuează, trebuie să inspectați dacă este vorba de o modificare intenționată sau neintenţionată. 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.

Configurarea presetării

Presetarea inițializează mediul şi este foarte dogmatic și se bazează pe ceea ce am găsit a fi util la Facebook. Toate opţiunile de configurare pot fi suprascrise aşa cum acestea pot fi personalizate atunci când nu se utilizează nicio presetare.

Mediu

react-native ships with a Jest preset, so the jest.preset field of your package.json should point to react-native. The preset is a node environment that mimics the environment of a React Native app. Because it doesn't load any DOM or browser APIs, it greatly improves Jest's startup time.

Personalizări 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. 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

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. În mod implicit presetarea mapează toate imaginile către un modul dublură de imagine dar dacă un modul nu poate fi găsit această opţiune de configurare poate ajuta:

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

Recomandări

Mock-uiți module native cu jest.mock

The Jest preset built into react-native comes with a few default mocks that are applied on a react-native repository. However, some react-native components or third party components rely on native code to be rendered. În astfel de cazuri, sistem manual de mocking din Jest poate ajuta pentru dublarea implementării.

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.

Uneori, este nevoie să furnizați o dublură manuală mai complexă. De exemplu în cazul în care doriţi să redirecţionaţi proprietăți sau câmpuri statice ale unei componente native către mock, puteţi returna o componentă React diferită dintr-un mock prin acest ajutor din jest-react-native:

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

Sau dacă doriţi să vă creați propriul mock manual, puteţi face ceva de genul acesta:

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

În alte cazuri, poate doriţi să mock-uiți un modul nativ, care nu este o componentă React. Aceeași tehnică poate fi aplicată. Se recomandă inspectarea codului sursă din modulul nativ şi logarea atunci când rulează o aplicaţie react native pe un dispozitiv real şi apoi modelarea unui mock manual după modulul real.

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.