From this article you will learn how to test React Native apps with Jest and Codemagic. React Native testing is important to ensure a sophisticated approach and confidence in delivering apps to the end-users
There are multiple types of tests for software applications – unit tests, component tests and integration tests. Let’s start by looking what are the differences between them.
Written by Sneh Pandya
React Native testing: types of tests
There are multiple types of tests for software applications that ensure a sophisticated approach and confidence in delivering apps to the end-users. But what are the differences between them? Let’s find out!
The primary types of tests are:
Unit tests: Unit testing ensures that each part of the code delivers the desired output. Developers only look at the interface and the specifications of the components. Thorough standalone testing of each component is performed before moving on to the next unit.
Component tests: Component testing is performed to verify the functionality and/or usability of a component, but it is not restricted to only these. Components can be anything that can take input(s) and deliver some output – for example, a code module, a web page, a screen and even a system inside a larger system.
Integration tests: Integration testing is performed to test individual components to check how they function together. It involves testing the integration between modules that are working fine individually. Integration testing provides clarity about the overall functionality of the application.
Introduction to React Native testing with Jest
Jest is a testing framework built using JavaScript and maintained by Facebook. Facebook itself uses the Jest testing framework to test their own React Native apps.
For React Native version 0.38 and above, Jest is included when you create a new project, so the following setup may already be completed for you.
Before testing React Native app with Jest, let’s start with configuring the React Native project.
Configure React Native project
- For our setup, we will install the library
jest
:
npm i jest --save-dev
npm install @testing-library/react-native --save-dev
npm install @react-navigation/native --save-dev
- Add the details in the
package.json
, as shown below:
"scripts": {
"test": "jest"
},
"jest": {
"preset": "jest-expo",
"setupFiles": ["<rootDir>/testing/jest-setup.js"]
}
Let’s say your app has one stack navigator and two screens. Your app would look something like this:
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
export const Screen1 = ({ navigation }) => (
<View style={styles.container}>
<Text>Screen 1</Text>
<Button title="Go to Screen 2" onPress={() => navigation.push('Screen2')} />
<StatusBar style="auto" />
</View>
);
export const Screen2 = () => (
<View style={styles.container}>
<Text>Screen 2</Text>
<StatusBar style="auto" />
</View>
);
const Stack = createStackNavigator();
export const AppStack = () => (
<Stack.Navigator>
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>
);
...
...
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f7f7f7',
alignItems: 'center',
justifyContent: 'center',
},
})
React Native testing: writing React Native integration tests
Let’s write our integration test. You don’t need to know how the app is implemented since you want to test the app from a black box testing perspective. Here’s what you need to know:
Screen1
is our initial screen in the app, which has a navigation function in place.The user should be able to navigate to
Screen2
when the button is pressed.
Here’s what the App.test.js
file looks like:
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import { NavigationContainer } from '@react-navigation/native';
import App, { Screen1, AppStack } from './App';
describe('Screen1', () => {
it('navigates on button press', () => {
const push = jest.fn();
const { getByText } = render(<Screen1 navigation={{ push }} />);
fireEvent.press(getByText('Go to Screen 2'));
expect(push).toHaveBeenCalledWith('Screen2');
});
});
Pretty straightforward test, right? The only thing specific to React Navigation that we had to implement here is passing a navigation
property to the component when we render it.
Next, we will create a testing setup file called testing/jest-setup.js
:
import 'react-native-gesture-handler/jestSetup';
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');
jest.mock('react-native-reanimated', () => {
const Reanimated = require('react-native-reanimated/mock');
Reanimated.default.call = () => {};
return Reanimated;
});
Running React Native integration tests
In your terminal, simply run npm test
to run the test for React Navigation with Jest that you just wrote.
You should also see an output saying:
PASS ./App.test.js
Screen 1
✓ navigates on button press (40ms)
AppStack
✓ renders the correct screen (32ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.64s, estimated 2s
Ran all test suites related to changed files.
Running tests on Codemagic
Codemagic is a popular CI/CD solution for mobile apps. One of its coolest features is running automated tests whenever a new commit or pull request is pushed in your Git repository.
To set up your React Native app on Codemagic, you can follow the steps provided here.
Once the project setup has been completed on Codemagic, you need to add the testing configuration in the codemagic.yaml
file, as shown below, for the tests to be executed:
workflows:
...
scripts:
- name: Install npm dependencies
script: npm install
...
- name: Tests # Insert before the build command
script: npm test
...
- name: Build ipa for distribution
script: xcode-project build-ipa --workspace "$CM_BUILD_DIR/ios/$XCODE_WORKSPACE" --scheme $XCODE_SCHEME
- name: Build Android app
script: cd android && ./gradlew assembleRelease
...
Once codemagic.yaml
is updated, you are ready to run your tests and build on Codemagic.
Codemagic can be configured to start the build process automatically after a commit or a pull request using build triggers. For now, we will trigger the build manually to start the tests and build process.
Just click on the Start new build button to trigger your build. Now wait for the build to complete, and it will show you the step results, including the test run.
Conclusion
Testing is extremely important when it comes to software development. Because there are multiple factors to consider, including performance improvements and a growing number of users, it is wise to integrate testing in your mobile apps starting from the early stage of development.
Jest is a popular choice when writing test cases for React Native. You can learn more about React Native testing with Jest from here.
Useful links and references
Here’s the documentation to get started with the Jest testing framework.
Here’s a case study on automating UI/integration tests with Flutter Driver and Codemagic.
Here’s a guide on why Android developers should pay attention to React Native in 2021.
Here’s a guide on how to run React Native Detox tests on Codemagic.
Here’s a guide on testing mobile apps with Codemagic’s continuous integration tool.
Here’s a guide on continuous integration and delivery for React Native apps.
Here’s a guide on how to develop and distribute iOS apps without Mac with React Native and Codemagic.
For discussions, learning and support, join the Codemagic Slack community.
Sneh is a Senior Product Manager based in Baroda. He is a community organizer at Google Developers Group and co-host of NinjaTalks podcast. His passion for building meaningful products inspires him to write blogs, speak at conferences and mentor different talents. You can reach out to him over Twitter (@SnehPandya18) or via email (sneh.pandya1@gmail.com).