preface
In 2018, after the company was successfully listed, it was required to ensure the stability and robustness of the code. All the two-party library and business library needed to be unit tested. At that time, the superior required that the code coverage of unit test should not be less than 70%. As the owner of unit tests for all ReactNative projects of the team, I sorted out a unit test document, and developed independently with each member based on the characteristics of unit tests. Finally, the coverage rate of all RN projects was over 95%. Just a little bit of time recently, I picked out a part of the unit testing related content to share with you…
Why do unit tests?
A lot of people have a question, but let’s look at a couple of scenarios
1. Functional testing
Problem: In the development process, some general functional tests with strong independence, if the integration test is carried out in the project, the compilation and testing process is relatively cumbersome, and the test code generally cannot be retained in the project, which is not conducive to subsequent maintenance or troubleshooting.
- Unit test has an independent running environment, which makes it convenient and quick to independently mock various logic of a module. In single test, it can quickly locate which function and line is not covered through code coverage, so as to avoid some logic being ignored. In addition, the unit test code is independent of the business and does not affect the business logic of the project, so the test cases can be retained for subsequent maintenance and troubleshooting.
2. UI component test
Problem: For some generic UI components that are not easily modified, such as encapsulated Refresh, Alert, and so on. This type of component is usually used in many files or projects. When changing this type of component, the scope of influence is large, and it cannot be modified casually.
- You can record the current tree through the Snapshot test in the unit test. When the code that affects the UI component changes, you can quickly and accurately locate whether the component has been modified and which line has been modified. If a component needs to be modified, you only need to update the corresponding snapshot tree.
3. Code testability
Problem: A lot of times, when we look at code we wrote a year ago and can’t believe we wrote it, we feel the urge to refactor. Most of the time, in order to catch up with the project schedule and other reasons, the correlation between the code modules we write is too large and the independence is not strong, resulting in poor maintainability
- Unit test, generally will test a file, a module, a function, or even a line of code, this code modularity and independence requirements are relatively high, general unit test more comprehensive code maintainability will be stronger.
What to use for unit testing?
Jest+Enzyme is a popular test combination of React projects. Facebook officially uses a single-test combination of Jest+ React-test-renderer for ReactNative.
-
Jest is an open source JavaScript unit testing framework based on the Jasmine framework developed by Facebook. It integrates test executor, assertion library, Spy, Mock, Snapshot and test coverage reporting. The ReactNative project itself was tested using Jest, so there was a good fit between the two.
-
2. React-test-renderer has a worse usage experience than Enzyme, but is friendly to reactNative. It is also a development framework recommended and used by Facebook in reactNative projects.
-
Enzyme is a test tool developed by Airbnb called React. React TestUtils extends React TestUtils and supports jquery-like find syntax to make assertions about render results. After practice, it is found that the Enzyme is mainly used for React single test, but not very friendly to ReactNative single test support. For example, mount will generate errors when compiling, so it is recommended to use react-test-renderer for UI-related tests.
How do unit tests work?
Configure the environment
1. Install the Jest
Yarn add --dev jest or NPM install --save-dev jestCopy the code
2. Install the Enzyme
Run the following command:
npm i --save-dev enzyme enzyme-adapter-react-16
Copy the code
See, the Installation
2. Install the react – test – the renderer
yarn add –dev react-test-renderer
3. Configure Babel to support ES6 syntax
yarn add --dev babel-jest babel-core regenerator-runtime
Copy the code
Note: you need to add the.babelrc file in the root directory of the project to configure the react-native default
{
"presets": ["react-native"]."sourceMaps": true// Use stack alignment to accurately locate unit test problems}Copy the code
4. Add the jest configuration to package.json
{
"jest": {
"setupFiles": ["<rootDir>/__mocks__/setup.js"]."collectCoverage": true."collectCoverageFrom": []."coveragePathIgnorePatterns": []."preset": "react-native"."transform": {
"^.+\\.js$": "babel-jest"
},
"transformIgnorePatterns": [
"node_modules/(? ! (react-native)/)"]."moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)": "<rootDir>/**mocks**/fileMock.js"}}}Copy the code
preset
Configure the react-native environment with. Babelrc file configuration and support react-Naitve compilationtransform
: Supports ES6/ES7 syntaxtransformIgnorePatterns
: ignore node_modules except (js – consultkit | react – native | medical – modules) outside of the filesetupFiles
: entry to configure mock files, which are compiled before the test casecollectCoverage
: Sets whether to display coverage ratecollectCoverageFrom
/ConsultIM/ SRC /**.jscoveragePathIgnorePatterns
: Sets files that do not need to be included in single-test coveragemoduleNameMapper
: represents the name of the resource to be Mock. If you need Mock static resources (such as img and file), you need to configure the Mock path, such as /mocks/xxMock.js
5. Add the setup.js and filemock. js files to the project
Setup.js unit test initialization entry, which is compiled before the test case, can introduce some mock file headers, etc
Filemock. js is used to mock out resource files (images, audio files, etc.), which can be empty
6. Run Jest to start unit testing
Yarn jest or yarn jest --watchCopy the code
See unit testing common instruction sets
7. Reference documents
Getting Started
Testing React Native Apps
Code coverage
Code coverage is a test metric that describes whether the code for a test case is executed. Istanbul is integrated with Jest, a code coverage tool that typically counts code coverage.
1. Four dimensions of measurement
Line coverage
: Whether each row of the test case is executedFunction coverage
: Whether every function of the test case is calledBranch coverage
: Whether each if block of the test case is executedStatement Coverage
: Whether each statement of the test case is executed
In each of the four dimensions, line coverage and statement coverage should be the same if the code is written properly. Will trigger a branch coverage, there are many kinds of basically has the following kinds: | |, &&,? ,! ,if statement,switch statement
2. Set coverage rate
Stanbul can set thresholds for each coverage on the command line and then check whether the test case meets the criteria. Each dimension is in relation to and, and an error is reported if one of the dimensions fails.
{... "jest": { "coverageThreshold": { "global": { "branches": 50, "functions": 50, "lines": 50, "statements": 50 }, "./src/components/": { "branches": 40, "statements": 40 }, }, "collectCoverage": true, "collectCoverageFrom": ["<rootDir>/src/HealthRecord/Common/**.js"], "coveragePathIgnorePatterns": [ "<rootDir>/src/HealthRecord/Common/HRUtil.js" ], } }Copy the code
-
- through
collectCoverage
To configure whether to display single test coverage. When true is enabled, the performance is reduced and the corresponding HTML file is generated to see which code has been overwritten
- through
-
- through
collectCoverageFrom
To configure the files that need to be counted for single test coverage
- through
-
- through
coveragePathIgnorePatterns
To configure files that do not require statistics on single test coverage
- through
-
- through
coverageThreshold
Configuration item to set coverage thresholds for different test dimensions. Global is a global configuration. By default, all test cases must meet this configuration to pass the test. Wildcard mode or path configuration is also supported. If these configurations exist, the coverage of matched files is removed from the global coverage calculation, using their own thresholds
- through
-
<rootDir>
Is the root path of the project
Common unit test instructions
1. Run all tests
jest
Copy the code
2. Run only the unit tests in a certain path
jest my-test
jest path/to/my-test.js
Copy the code
You can also run a unit test directly by clicking the triangle symbol before a unit test on the compiler
3. Listening mode
jest --watch
jest --watchAll
Copy the code
That is, unit tests are automatically run whenever code changes are made and saved
4. Display coverage rate
jest --coverage
Copy the code
At runtime, the coverage report is displayed on the terminal and the corresponding HTML file is generated in the project as the coverage report
5. Forcibly stop other occupations and run the current test
jest --detectOpenHandles
Copy the code
When running a unit test, it sometimes prompts you that there are other threads occupying the current unit test. Run this directive to force the other threads to stop occupying and run the current test
6. Reference documents
Jest CLI Options