Automated React Native tests using UI Automator

Ryan von Kunes Newton
4 min readNov 8, 2017

--

Writing unit tests for React Native is fairly straight forward using tools like Jest or AVA. However, I had a few questions from our QA department about integration tests, so I decided to play around with Android’s UI Automator a little bit. This is a quick walkthrough of what I explored. The repo I built can be found here.

Create the React Native app

There’s plenty of guides and additional complexities to this, but I just followed the simple instructions under “Building Projects with Native Code” section on React Native getting started. I quickly threw together a TouchableOpacity that toggles a green square on and off.

The plan was to test the presence of the box and whether the toggle worked. The JS code.

Toggling

Setting up the Android tests

I followed this guide to some extent, although needed to work around a number of issues. Start off by adding the test runner dependencies to build.gradle and re-syncing gradle.

Creating and running a basic test was actually a bit of a pain. In Android Studio move the cursor to the class you want to test and hit Command+Shift +t and a dialogue will appear with “Create New Test…”.

The directory structure is actually when running the tests. Instrumented tests should end up in app/src/androidTest/. Read more about android test directory structure.

You will also need to create a new configuration. This can be done through “Edit configurations” next to the Run button.

I created a configuration called InstrumentationTests and set android.test.InstrumentationTestRunner as the test runner for that configuration.

Using the UI Automator Viewer

The UI Automator Viewer was one of the cool things I discovered during this. It lets you take a ‘screenshot’ of your emulator and inspect the Views on the screen. It’s scope is the whole phone, so you can inspect things even outside of your app.

Click on different views from the screenshot and look at their respective properties.

Note: if you have trouble finding the UI Automator View, it is located in your Android SDK folder. If you have trouble finding your Android SDK folder, here is a Stack Overflow answer for you.

Properties that we can see that are particularly important for us as selectors are content-desc and text. Traditionally the resource-id has been an important identifier as well, but there was a bit of discussion within the React Native community where they decided not to support it for now. Instead, when creating components on the React Native side, you will have to use the AccessibilityLabel prop on views to set the content-desc.

Writing the tests

You can take a look at the full test file here.

We use the UiDevice class to control the emulator, navigate to home, and open up the app.

// Open the simulator and head to the home screen
device = UiDevice.getInstance(getInstrumentation()); device.pressHome();
device.wait(Until.hasObject(By.desc("Apps list")), 3000);
// Open up the list of apps
UiObject2 appsButton = device.findObject(By.desc("Apps list")); appsButton.click(); device.wait(Until.hasObject(By.text("TestAutomator")), 3000);
// Open our app
UiObject2 testAutomatorApp = device.findObject(By.text("TestAutomator"));
testAutomatorApp.click();

Note: TestAutomator is the name of my app. Also, I used to UI Automator Viewer to figure out that "Apps list" was the content-desc for the apps button.

In the tests, we use a BySelector to select various elements on the screen. There are number of different selector methods. It’s more concise to use the content-desc , but as you can see in the example above, I use By.text(“TestAutomator”) to pick out the app by the text in its name.

Here is a test I wrote to ensure that the green box appeared when the button was pressed:

BySelector greenBoxSelector = By.desc("greenBox");
BySelector buttonSelector = By.desc("toggleButton");
// Find the toggle button and click it
device.wait(Until.hasObject(buttonSelector), 3000);
UiObject2 button = device.findObject(buttonSelector); button.click();
// Find the green box and assert it exists device.wait(Until.hasObject(greenBoxSelector), 3000);
Boolean greenBoxExists = device.hasObject(greenBoxSelector); assertTrue("The green box exists", greenBoxExists);

The UiObject2 class is used for interacting with selected objects. To check whether they exist or not, use device.hasObject, which returns a Boolean, rather than device.findObject.

Another thing to take note of is the wait. In automated tests there is often a delay for things to load or render so you have to wait or put a delay in otherwise your new view will not be found.

In addition to the one test ensuring that the box appears, to be on the safe side I also wrote one to ensure there is no green box at the start.

Running the tests

Now that I have my tests and configuration in place, I could select my configuration from the dropdown next to the “Run” button and hit run. Here are the two tests being run entirely automated.

--

--

No responses yet