React Native makes it easy to create mobile applications for both iOS and Android.
Developers create the mobile app with Javascript and then have React Native compile these into native mobile apps. The mobile apps that React Native creates look and behave exactly as apps created with Java/Kotlin or Objective-C/Swift.
The project was created by Facebook and is still maintained by Facebook, it regularly receives updates and fixes. The main advantages of using React Native:
- It makes developing apps much faster: you don't have to recompile after every change, and your code will work on both iOS and Android. No need to write code twice.
- You can still run native code inside React Native. If you have existing code, or third-party code you want to use, you can use it with React Native.
- There's a big eco-system of developers and other engineers who can help and answer your questions. Because it's so popular, it's a very stable project with regular bugfixes.
In this article, we'll go through the steps necessary to create an application, modify it for automated testing and then test it automatically via Appium on TestingBot.
Creating a React Native Application
To get started, please install React Native:
npm install -g react-native-cli
Once you have installed React Native, it is time to create our project:
react-native init TestingBotDemo
cd ios && pod install
This will create a skeleton of files and set everything up for you to test/create your mobile application.
To get started, let's create our main component. We'll create a basic calculator that will require two numbers and show you the sum of those numbers.
import React, { Component } from 'react'
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
TextInput,
} from 'react-native'
class App extends Component {
constructor(props) {
super(props)
this.state = {
inputA: 0,
inputB: 0,
sum: 0
}
this.onInputAChange = this.onInputAChange.bind(this)
this.onInputBChange = this.onInputBChange.bind(this)
}
onInputAChange(inputA) {
this.setState({ inputA }, () => {
this.updateSum()
})
}
updateSum() {
const { inputA, inputB } = this.state
const sum = parseInt(inputA, 10) + parseInt(inputB, 10)
this.setState({ sum })
}
onInputBChange(inputB) {
this.setState({ inputB }, () => {
this.updateSum()
})
}
render() {
const { sum, inputA, inputB } = this.state
return (
<SafeAreaView>
<View style={styles.container}>
<Text>InputA</Text>
<TextInput
editable
maxLength={5}
value={inputA.toString()}
onChangeText={this.onInputAChange}
testID= {"inputA"}
accessibilityLabel= {"inputA"}
/>
<Text>InputB</Text>
<TextInput
editable
maxLength={5}
value={inputB.toString()}
onChangeText={this.onInputBChange}
testID= {"inputB"}
accessibilityLabel= {"inputB"}
/>
<Text>Sum</Text>
<TextInput
editable={false}
value={sum.toString()}
/>
</View>
</SafeAreaView>
)
}
};
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
display: 'flex',
marginTop: 32,
paddingHorizontal: 24,
}
});
export default App;
This example App creates a view with 2 input fields (InputA
and InputB
).
Once the user puts in some numbers, the state will update and the sum will be shown in Sum
.
Preparing your React Native App for UI Testing
The important part we want to focus on here are the testID
and accessibilityLabel
attributes.
These are the attributes that allows your Automated Test to quickly locate the input fields.
For iOS tests with XCUITest, the testID
makes it much easier to locate an element in your tests.
You can use the value specified in this attribute as a locator for your Appium tests.
This works much better than using XPath
for locating elements, because an XPath expression can become complicated very fast, and is prone to change.
Android testing via Espresso or UIAutomator does not use this testID
attribute. Instead, you can use the accessibilityLabel
in your tests for Android tests.
Testing your React Native app with Appium
Now that we have prepared our app for testing, we can run a test that will add some simple numbers and verify if the calculator works:
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
desired_caps = {
"deviceName": "Galaxy S8",
"platformName": "Android",
"version" : "9.0",
"app": "https://testingbot.com/appium/sample.apk",
"realDevice": true
}
driver = webdriver.Remote("http://key:secret@hub.testingbot.com/wd/hub", desired_caps)
inputA = WebDriverWait(driver, 30).until(
EC.element_to_be_clickable((MobileBy.ACCESSIBILITY_ID, "inputA"))
)
inputA.send_keys("10")
inputB = WebDriverWait(driver, 30).until(
EC.element_to_be_clickable((MobileBy.ACCESSIBILITY_ID, "inputB"))
)
inputB.send_keys("5")
sum = WebDriverWait(driver, 30).until(
EC.element_to_be_clickable((MobileBy.ACCESSIBILITY_ID, "sum"))
)
if sum!=None and sum.text=="15":
assert True
else:
assert False
driver.quit()
This will launch the app on a physical Android device in the TestingBot datacenter.
The test will locate both inputs, put in a number, and then verify if sum
is correct.
We have a lot of more documentation on mobile app testing in our documentation section.
Conclusion
React Native provides an easy framework to quickly write mobile apps for both iOS and Android. It has very good test frameworks, such as Jest, to create functional and unit tests with snapshots.
It is important to write end-to-end tests, testing the UI and functionality of your app on real devices, before your release it on the App Store. With Appium testing, automated tests will mimic the action of your end users; tapping, swiping, etc.
TestingBot provides mobile devices (real devices and emulators) to run your tests on a variety of configurations (different OS versions and device specs).
If you'd like to get started with mobile app testing, please sign up for a free account and try our easy to follow tutorial on mobile app testing with Appium.