Easy Espresso tests: use Barista
Having UI tests for your app is quite powerful.
This is especially true for side projects where your releases might be infrequent. The feature you built for the previous version and you manually thoroughly tested might be broken by the new shiny feature. And you don't have the time to thoroughly test again. Sometimes, not even for a sanity check due to limited time, or more commonly, because you forgot about it.
This is where UI testing comes in. It's like having a robot arm you instruct where to click. All you need to do is to write a UI test for each of the features you want to ensure are working. Then before releasing a new version you run your UI tests making sure nothing is broken.
This sounds easier than it is in reality. Espresso, the official framework for writing Android UI tests, is super flexible but quite specific. For clicking a button, you need to specify exactly where the button is. And with a minor change in the UI, the test will need adjustments.
So when I discovered Barista I was pleasantly surprised. Generally speaking, it's a bunch of static methods for common actions and assertions. Using Barista you can write way more cleaner UI tests for your apps, without Googling around for how to do the simplest thing (because the authors of the library did that for you). Of course, it doesn't cover everything. But in those more advanced cases, you can use plain Espresso.
Set up
Add this to your build.gradle
. Please check for the latest version before copy-pasting.
Rules
Rules are useful for setting up and cleaning up before and after your tests respectively. Barista offers a convenient rule for clearing preferences/databases/files and auto-retrying your failed tests.
@RunWith(AndroidJUnit4::class)
class DemoTest {
@Rule
@JvmField
val baristaRule: BaristaRule<MainActivity> =
BaristaRule.create(MainActivity::class.java)
@Before
fun setUp() {
baristaRule.launchActivity()
}
}
The @Before
section runs before every test and launches the activity under test.
Actions
Barista offers convenient static methods for common actions you can perform in an Android app. The common thing is that they are performed only on visible views and that scrolling to reach a view is handled automatically (in contrast with plain Espresso). This makes the test a bit more flexible when minor UI refactoring takes place since your test won't break as easily as before.
Some sample actions follow (to indicate how simple the API is) but you can see the full list here.
clickOn(R.id.button)
clickOn("Next")
clickMenu(R.id.menu_item)
writeTo(R.id.edittext, "A great text")
clickListItemChild(R.id.list, 3, R.id.row_button)
clickDialogPositiveButton()
Assertions
Some convenient assertions are offered as well. The same rules apply: only visible on the screen and scrolling is handled for you. List of all supported assertions.
assertDisplayed("Hello world")
assertDisplayed(R.id.button, "Hello world")
assertContains(R.id.textview, "text")
assertNotDisplayed("Hello world")
assertNotExist(R.id.button)
assertChecked(R.string.checked_checkbox)
In case you want slightly more advanced matching you can use custom assertions. They let you match UI elements by their resource ID, text, or viewMatcher
. Once you have a match, you can assert any property of the matched element.
assertAny<Button>("Save") {
it.enabled == true
}
assertAny<RadioGroup>(R.id.radioGroup) {
it.checkedRadioButtonId == R.id.option1
}
Caveats
The only downside I found was that the predefined actions are not enough to cover most of the apps out there. For instance, I had trouble clicking on things inside AndroidX AlertDialogs
. But for those things you can always fall back to plan Espresso. Another common thing is for waiting UI elements to appear before proceeding that I briefly covered in a previous post.
By now you should know how to use Barista to write easier, cleaner, and less fragile UI tests. A good read if you want to dive deeper a bit further, written by the library authors. Happy testing!