Testing verifies that the system meets the different requirements including, functional, performance, reliability, security, usability and so on, more so on larger teams. However, it’s not uncommon for testing to be deferred or outright ignored in favor of pushing out new features or not having enough resources. Sometimes developers do have the time and resources, but unfortunately don’t see the point of writing and maintaining tests, especially because writing UI tests with Espresso can be challenging and un-intuitive for people who have not done it before.

Without Robot Pattern

You can write your own Espresso tests old MVC style, you also have the option to “record” Espresso test, go to Run -> Record Espresso Test start clicking through the app to record the test and once you’re done, Android Studio will generate a nice big blob that looks like something like this:

Now at first glance, it looks horrible, but on second glance… yeah, it’s still horrible. It is kinda messy and hard to understand.

With Robots

As developers we often get caught up in our very own technical world, tapping the buy button is finding the view by ID and performing a click, displaying a cart view is clicking on the cart, inflating the layout and attaching to another view to be displayed, etc… however from a QA or a user perspective tapping the buy button is just tapping the buy button, viewing the cart is tapping the the cart and viewing your cart and in the end that is what matters. Testing your business-critical flows from a users perspective.

With a little help from the Kotlin DSL capabilities and the Robot pattern, we’ll architect our UI tests to be easy to write, easy to understand and easy to maintain by anyone.

Kotlin DSL

A domain-specific language (DSL) is a computer language specialized to a particular application domain. This is in contrast to a general-purpose language (GPL), which is broadly applicable across domains.

Basically, it means we can optimize and constraint the language for our particular application use-case and since we’re not writing a DSL from scratch we’re just using Kotlin to write our own DSL, we’re writing internal DSL.

If you want to know more about writing DSL, please refer to these resources.

Robot pattern

Robot pattern is open for interpretation, but the goal is to abstract the high-level actions we would take on a view from the actual code implementation.

Let’s take a look at our Post creating screen.

We have user input for text, a button to submit the post and a text to display the result of submitting the post.

Let’s write a test for a successful post submission for our screen in Espresso without any architecture or patterns.

If a submission is successful, we expect a message Post Submitted.

Even for this tiny example, there is a lot of code involved that's relatively hard to read and it can easily explode like the example in the intro.

Let’s refactor our test a little bit.

First, we’ll create some helper functions that we’ll be using often.

Next, we’ll create a BaseTest class that will help us with robot creation and we’ll utilize Kotlin’s DSL capabilities.

Now it’s time to write our first Robot.

We use the extension functions that we created to help us with typing text or clicking buttons and since we’re extending BaseRobot every method is going to return the object itself which will help us write the tests in a DSL way.

And finally writing the tests.

We have now abstracted the actions from the implementation, compared with our initial code this is much more readable, anyone can understand what’s going.

We have separated what we’re testing from how we’re testing it.

In our test, we’re testing the user entering text into EditTex , submitting that text by clicking a submit Button and finally verifying that the text has been successfully submitted by checking the TextView text.

What if the designs have changed and the Button now needs to be ImageView instead?

What we’re testing, from a user’s point a view hasn’t changed, we’re still testing entering text and submitting that text, meaning no changes are necessary for our test flow.

How we’re testing has changed, we’ll have to modify our Robot to reflect the changes.

Now imagine a screen with dozens of views and interactions that need to be redesigned…

Each screen is going to have its own robot, we can compose the robots in the tests to create more complex flow.

We saw that testing code doesn’t have to be a pile of spaghetti that nobody wants to touch or know how to make. Just by glancing at the code we can see what we’re testing and the underlying implementation doesn’t really matter anymore. The final result is a readable, maintainable and properly architected test suite that will make any engineer happy to get in there do add even more tests.

https://github.com/igor-brishkoski/AndroidRobots

References