Android test frameworks have gone through multiple refinements from the moment this operation system reached the public. In this article, I will pay attention to the syntax of all Android native test frameworks: UiAutomator, Espresso, Compose UI test.
The first one that went out was UiAutomator with its successor UiAutomator2. This framework is still in use and has shown resiliency within a time. Even now many third-party Android test frameworks rely on it. If you will use it for a while it will be clear that the test syntax was not the main focus of its authors. The test code looks bulky, the test assertions are fully on you, and failures with
NullPointerException in the stack trace don’t tell you much. Below is an example of how you would locate an object that contains a
"button" text and assert it exists, i.e. it is not
You can imagine how your UI test case code will blow up even with the medium test size – around 10 steps. And the similar situation is with the UiAutomator2 which didn’t change much compared to its predecessor:
As you can see they are quite similar and, to be honest, readable enough. Not perfect but ok. But the inconvenience in its use becomes noticeable very fast – every time you would like to perform an action or assertion, or both on an object you should write a new line of code again and again. Very similar to what iOS test framework xctest proposed at that time (and even now, unfortunately).
Some years have passed and what we see – the Espresso Android UI test framework was open-sourced. Despite the fact that it aimed mainly at developers’ use it gained much popularity in UI (end-to-end) test automation due to its clear syntax, ease of use, and the possibility to combine multiple actions and assertions. This was achieved mainly by integrating Hamcrest matchers into it. On top of that Hamcrest matchers improved test failures exceptions a lot because of the description given to each matcher.
Here is the code that performs the same task as UiAutomator code above:
I can admit that in simple UI hierarchy cases Espresso performs really well. The code is clean, readable, easy to follow when analyzing test failures. Also, the failure stack trace is good enough and helps you to narrow down or analyze it with almost no effort. But what happens when the layout hierarchy is complex and you for some reason can’t update the desired view properties to uniquely identify it? Then the following case may occur:
Well, can you get from the first look what is going on here? Probably not. But as such cases are rare, Espresso (with Hamcrest) holds the leading position among reviewed frameworks so far.
Compose UI test
Just before Compose UI announcement I was waiting for the improved “Espresso” like test framework but I was disappointed a bit when it was released. From my point of view, the Compose UI test framework was impacted by some third-party test frameworks, and as shown below you have to provide multiple boolean parameters that control how some functions should behave. This requires you to know the default parameters values plus such syntax is much harder to read compared to Espresso one. Also, the amount of code is usually bigger than it can be.
Let’s see with the time how comfortable it will be in use. For now, I’m a bit skeptical.
- There is no clear strategy on Google (Android) side how their test frameworks should look like. With each new test framework developers and automation engineers have to invest time into learning new APIs.
- It is visible that differnt teams on Android side are responsible for test framework development that leads to a different simantics in each of them. Yes, we can say that platform has migrated from Java to Kotlin programming language which impacted a lot the test APIs. But they could do better – this is Google at the end.
- Keep in mind that now to write automated UI tests on Android you should know all three test frameworks (maybe 2 if you focus on integration testign level only).