Detox: End-to-End Testing library
Setting up Detox using React Native and AppCenter
Mobile automation baked into the entire pipeline from start to finish using Detox — React Native & App Center
Having the right test automation is the key to the success of any Product. Testing your application from the perspective of an end-user automatically, ensuring the quality of code, along with delivering it, on the right medium available.
There are various tools when it comes to web automation like Cypress, WebdriverIO, and many others. But when it comes to mobile, automation is not that common. The reason for writing an article on mobile automation is to explain how to achieve and implement end-to-end testing of mobile using Detox and integration with CI/CD pipeline like AppCenter for distribution.
Why Detox?
Detox an End to End testing library for applications that are developed using React Native and for pure native applications. It allows mobile tests to be performed by running a real device/simulator and showcasing the interaction like a real User. Less flaky Cross-Platform, supports both android and IOS Debuggable Made for CI
Note: Let's focus on iOS, otherwise the length of the article will become too long.
The following React Native versions have been tested: iOS Android <=0.62 <=0.56 — Full support
=0.57 <=0.62 — Visibility edge-case: see this RN issue*
Let’s get Started
Prerequisites:
- Mac with macOS
- Xcode
Create a sample react-native application
1. Install react-native
$ npm install react-native -g
2. Setup react-native via command line
$ npx react-native init <project_Name>
3. Launch the app by navigating within your project
$ react-native run-ios
4. Install the latest version of Home Brew
$ brew tap wix/brew
5. Install the latest version of apple-simutils
$ brew install applesimutils
6. Install Detox command-line tool
$ npm install -g detox-cli
7. Add Detox as a dev dependency for the project
$ yarn add detox -D
Add Detox configuration
Let's add detox configuration to your project. Always try keeping the detox configuration separate in your package.json file. I have added 2 configurations, one in case of debug mode to run it locally and one in release mode while trying to integrate it with a CI/CD pipeline.
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/DetoxTest.app",
"build": "xcodebuild -workspace ios/DetoxTest.xcworkspace -scheme Staging -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"device": {
"type": "iPhone 11 Pro"
}
},
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/DetoxTest.app",
"build": "export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/DetoxTest.xcworkspace -scheme Staging -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet",
"type": "ios.simulator",
"device": {
"type": "iPhone 11 Pro"
}
}
},
"test-runner": "jest",
"runner-config": "e2e/config.json"
}
}
Now, let's install one of the frameworks either jest or mocha.
1. Install detox-cli for jest or mocha
$ detox init -r jest
OR
$ detox init -r mocha
It will create an e2e folder in your project, with some basic test files which allow you to start writing your first script, init.js, and some config files, wherein you can mention the type of reporting required.
There are various reporters available, but I tried using jest-stare as it gives reports in both HTML and JSON format.
2. Install jest-stare reporting
$ npm i jest-stare
Now, change the config.json
file to use the reporter you just added. By defining the jest-stare reporter, e.g
"reporters": ["../node_modules/jest-stare"]
Its always important to maintain the folder structure, so that the effort is always streamlined, hence better to keep common things together. I have tried keeping the specs in one folder and user data in a separate JSON file. Let’s do it!
- Create a sub-folder under e2e naming it specs and add all the specs files underneath
e2e
├── specs
- Create a JSON file under e2e mentioning it as users.json, wherein you will store all the user-related information. As a part of testing, we always need to keep in mind having separate user data for each environment. Why not make it configurable? Let's do that
e2e
├── specs
└── user.json{
"dev": {
"devLoginDetails": {
"username": "abc@gmail.com",
"password": "12345"
}
},
"stage": {
"stgLoginDetails": {
"username": "cdf@gmail.com",
"password": "98765"
}
}
}
- Now, let's create a environment file and name it testEnvConfig.js
wherein you will mention the environment-specific data, like in our case we have users specific to the environment
process.env.ENV_NAME = "dev"
- Add, testID for the element you want to perform action now. Move to the source code of your project, identify the element and add testID like below:
testID={'basics'}
- We shall now modify our firstTest.e2e.js
to verify some elements from the react welcome page
describe("Verify the react welcome page elements", () => {
beforeEach(async () => {
await device.reloadReactNative()
}) it("should have welcome screen", async () => {
await expect(element(by.id("welcome"))).toBeVisible()
}) it("should be able to click on basics link", async () => {
await element(by.id("basics")).tap()
await expect(element(by.text("The Basics"))).tap()
})
})
- In order to execute the tests, we first need to build the app using detox commands
$ detox:build
- Followed by the command to run tests under specs folder, use
$ detox:test e2e/specs
- This will now generate a jest-stare folder within your project, which will have HTML and JSON reporting files, mentioning all the failed and passed test cases. Along with detailed summary for test scenarios under the specs file
What's next now?
Yes, as promised we will see the functional tests written in detox to be integrated with CI/CD tools like app center. Having automation scripts is wonderful, but would it make sense if there is an error in code and scripts fail. But your app getting delivering to various environments. The most important part of having automation scripts is to reduce manual effort and having automated deployment and failing the deployments in case of errors.
Every CI/CD has its own shell files. In the case of appcenter we do have multiple files for executing functions before build (post-build), after build (pre-build), Post-clone, and various others. Let's focus on appcenter-pre-build.sh
file, wherein our app has started building and then let's add our commands to execute E2E testing before building the app
- Build the app via detox
echo "Building the project for Detox tests..."
npx detox build --configuration ios.sim.release
- Step 2: Execute our E2E tests via Detox
But is that enough?
We still haven't stopped the distribution of the app when your tests fail. Here’s a solution provided by app-center, wherein you can use app-center’s open API to cancel the build, using the token
echo "Executing Detox tests..."
if npx detox test e2e/specs/firstspec.e2e.js --configuration ios.sim.release --cleanup; then
echo "All tests succeeded"
else
echo "Test failed"
echo "Cancelling app center build"
API_TOKEN="<UserToken>"
OWNER_NAME="<ownerName>"
APP_NAME="<appName>"
curl -iv "https://appcenter.ms/api/v0.1/apps/$OWNER_NAME/$APP_NAME/builds/$APPCENTER_BUILD_ID" \
-X PATCH \
-d "{\"status\":\"cancelling\"}" \
--header 'Content-Type: application/json' \
--header "X-API-Token: $API_TOKEN"
exit
fi
Yahoo!! We have successfully implemented our e2e with CI/CD..
Summary
There are various elements that help you perform different operations and actions of the device, the list is available here. Also, tools like Detox helps increase the speed and can be easily integrated with react native apps. The community is growing faster. Have you used Detox for mobile app testing?
Happy using Detox!! 👻
Don’t forget to follow The Lean Programmer Publication for more such articles, and subscribe to our newsletter tinyletter.com/TheLeanProgrammer