Main idea of this talk is to show what technologies can be used for cross-platform mobile app development and how to deal with UI tests automation for them. I will outline set of challenges every tester and developer needs to conquer and give some tips how to solve them. During this talk I will present how to apply UI tests in React Native project using Detox framework.
3. Agenda
1. Introduction
2. Cross-platform frameworks for mobile development
3. UI testing approaches for hybrid apps
4. Detox guide for applying UI tests in React Native projects
4. Agenda
1. Introduction
2. Cross-platform frameworks for mobile development
3. UI testing approaches for hybrid apps
4. Detox guide for applying UI tests in React Native projects
5. Agenda
1. Introduction
2. Cross-platform frameworks for mobile development
3. UI testing approaches for hybrid apps
4. Detox guide for applying UI tests in React Native projects
6. Agenda
1. Introduction
2. Cross-platform frameworks for mobile development
3. UI testing approaches for hybrid apps
4. Detox guide for applying UI tests in React Native projects
16. The Native white Box Test
+ Fast
+ Easy setup
+ Wide range of open source
helpers
+ Compatible with Cloud Device
Farms
17. The Native white Box Test
+ Fast
+ Easy setup
+ Wide range of open source
helpers
+ Compatible with Cloud Device
Farms
− Different languages in project
repository
− Duplicated test code
19. The Cross Platform Black Box Test
+ Many supported languages
+ Wide community
+ Similar to Selenium
+ Single test code base
+ Compatible with Cloud Device
Farms
20. The Cross Platform Black Box Test
+ Many supported languages
+ Wide community
+ Similar to Selenium
+ Single test code base
+ Compatible with Cloud Device
Farms
− Slow
− Difficult debugging
− Lack of stability
22. The Cross Platform Gray Box Test
+ Fast
+ Easy setup
+ Single test code base
+ The same language as default
project one
+ Close integration with source
code
+ API designed for a specific
platform
23. The Cross Platform Gray Box Test
+ Fast
+ Easy setup
+ Single test code base
+ The same language as default
project one
+ Close integration with source
code
+ API designed for a specific
platform
− No way / difficult to integrate
with Cloud Device Farm
− No outspread community
− Often still not developed
enough
34. How to make apps testable?
<Text
style={styles.textStyle}>
{!this.state.clicked? defaultButtonText: "Polidea"}
</Text>
<Text
accessible= {true}
testID= {"ButtonText"}
accessibilityLabel= {"ButtonTextDesc"}
style={styles.textStyle}>
{!this.state.clicked? defaultButtonText: "Polidea"}
</Text>
35. How to make apps testable?
<Text
accessible= {true}
testID= {"ButtonText"}
accessibilityLabel= {"ButtonTextDesc"}
style={styles.textStyle}>
{!this.state.clicked? defaultButtonText: "Polidea"}
</Text>
36. How to write Test scripts - API Overview
Detox Object
Test plan
configuration
Device Object
Key events, Gestures,
Device settings
Matchers, Actions, Expectations
Finding Views, User’s actions, Validation
API
37. How to write Test scripts - Init script by example
require('babel-polyfill');
38. How to write Test scripts - Init script by example
require('babel-polyfill');
const detox = require('detox');
const config = require('../package.json').detox;
39. How to write Test scripts - Init script by example
require('babel-polyfill');
const detox = require('detox');
const config = require('../package.json').detox;
beforeAll(async () => {
await detox.init(config);
});
40. How to write Test scripts - Init script by example
require('babel-polyfill');
const detox = require('detox');
const config = require('../package.json').detox;
beforeAll(async () => {
await detox.init(config);
});
beforeEach(async () => {
await adapter.beforeEach();
});
41. How to write Test scripts - Init script by example
require('babel-polyfill');
const detox = require('detox');
const config = require('../package.json').detox;
beforeAll(async () => {
await detox.init(config);
});
beforeEach(async () => {
await adapter.beforeEach();
});
afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
42. How to write Test scripts - Test class by example
43. How to write Test scripts - Test class by example
describe('Example', () => {
44. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
45. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await
46. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device
47. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
48. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor
49. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element
50. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText')))
51. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible()
52. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
53. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it
54. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
55. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
await element(by.id('ButtonText'))
56. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
await element(by.id('ButtonText')).tap();
57. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
await element(by.id('ButtonText')).tap();
await waitFor(element(by.text("Press Me")))
58. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
await element(by.id('ButtonText')).tap();
await waitFor(element(by.text("Press Me"))).toNotExist()
59. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
await element(by.id('ButtonText')).tap();
await waitFor(element(by.text("Press Me"))).toNotExist().withTimeout(2000);
60. How to write Test scripts - Test class by example
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
await waitFor(element(by.id('ButtonText'))).toBeVisible().withTimeout(10000);
});
it ('should Press me text be morphed in Polidea title after click on button',async
() =>{
await element(by.id('ButtonText')).tap();
await waitFor(element(by.text("Press Me"))).toNotExist().withTimeout(2000);
await waitFor(element(by.text("Polidea"))).toBeVisible().withTimeout(100);
});
})
62. How to integrate With CI - Gitlab CI
detox_test:iOS: detox_test:android:
63. How to integrate With CI - Gitlab CI
detox_test:iOS:
stage: test
before_script:
detox_test:android:
stage: test
before_script:
64. How to integrate With CI - Gitlab CI
detox_test:iOS:
stage: test
before_script:
detox_test:android:
stage: test
before_script:
- adb connect pixel:5555; sh ./scripts/waitForDevice.sh
pixel
65. How to integrate With CI - Gitlab CI
detox_test:iOS:
stage: test
before_script:
- brew tap wix/brew
- brew install --HEAD applesimutils
- npm install -g detox-cli
- npm install -g react-native-cli
- npm install
detox_test:android:
stage: test
before_script:
- adb connect pixel:5555; sh ./scripts/waitForDevice.sh
pixel
- mkdir -p ./detox_node/
- npm install --prefix ./detox_node/ -g detox-cli
- npm install --prefix ./detox_node/ -g react-native-cli
- npm install
66. How to integrate With CI - Gitlab CI
detox_test:iOS:
stage: test
before_script:
- brew tap wix/brew
- brew install --HEAD applesimutils
- npm install -g detox-cli
- npm install -g react-native-cli
- npm install
script:
detox_test:android:
stage: test
before_script:
- adb connect pixel:5555; sh ./scripts/waitForDevice.sh
pixel
- mkdir -p ./detox_node/
- npm install --prefix ./detox_node/ -g detox-cli
- npm install --prefix ./detox_node/ -g react-native-cli
- npm install
script:
67. How to integrate With CI - Gitlab CI
detox_test:iOS:
stage: test
before_script:
- brew tap wix/brew
- brew install --HEAD applesimutils
- npm install -g detox-cli
- npm install -g react-native-cli
- npm install
script:
- react-native start --port 2137 &
detox_test:android:
stage: test
before_script:
- adb connect pixel:5555; sh ./scripts/waitForDevice.sh
pixel
- mkdir -p ./detox_node/
- npm install --prefix ./detox_node/ -g detox-cli
- npm install --prefix ./detox_node/ -g react-native-cli
- npm install
script:
- ./detox_node/bin/react-native start --port 2137 &
78. Key TAkeaways
● Cross platform apps can be tested with the same
frameworks as native ones
● For typical apps you can avoid code duplication and use cross-
platform frameworks
● Detox is a great tool for React Native UI testing