Easy Instrumented Tests (UI Tests) for Android in 2021
In the previous post, we’ve got familiarized with unit testing. Now is the turn for test our UI’s.
What are Instrumented tests? 🤔
Instrumented tests are tests that run on physical devices and emulators, and they can take advantage of the Android framework APIs and supporting APIs, such as AndroidX Test.
Official documentation.
Our goal with instrumented tests is to verify the “actions” that the user can perform like clicking a button, writing on a EditText, or verify if some views are visible or not on a given view state.
Once we have our unit tests running successfully we know that our methods works as expected, but what about our views?… Are they rendering or behaving as expected? How can we be sure that the views are correctly displayed or the buttons are calling the right methods after a onClick
event?
Well, that’s exactly why Instrumented tests exist. With the help of libraries like espresso, fragment tests, etc. we can launch our activities or fragments into a emulator or a physical phone and validate the things we mention before.
We are going to run an Instrumented test on this screen and verify if the views are displaying correctly according to the view state model.

Set up 🛠️
From my point of view, this could be the part that it’s most difficult for us because we usually get libraries conflicts, some weird gradle errors and didn’t even reach to run our UI tests. It is important to see that in this case, the project im working on is using Koin as service locator in order to provide the dependencies my classes need.
If you are using something else like Dagger — Dagger Hilt probably you’ll need to change or add some other dependencies in order to set up your UI tests. After the set up part, everything remains the same. (Dagger hilt has good documentation and the library is getting better and better, Im planning to migrate from koin to hilt and write about it).
Let’s start by adding the following dependencies to our build.gradle file
// The versions listed here are the ones at the time im writing this blog.
dependencies {//... Other dependenciesandroidTestImplementation "androidx.test.espresso:espresso-core:3.3.0"androidTestImplementation "io.mockk:mockk-android:1.11.0"androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.0"androidTestImplementation "io.insert-koin:koin-test-junit4:3.0.2"debugImplementation "androidx.fragment:fragment-testing:1.3.3"}
Now, inside the android
block in the same file, add the following
android {
...
defaultConfig {
...
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
} ... testOptions {
animationsDisabled = true
} ...
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
exclude 'META-INF/LGPL2.1'
exclude 'META-INF/AL2.0'
exclude("META-INF/*.kotlin_module")
}
}
In the android.defaultConfig
block add the testInstrumentationRunner
for be able to “launch” our tests, in the case you use a custom application class for your tests you must implement your own instrumentation runner and override that value for the package location of your custom instrumentation runner.
The android.testOptions
will disable the animations if any in order to avoid some other error types. Finally, in the android.packagingOptions
block exclude the files from above, in order to avoid weird compilations errors.
Code time 🎧💻💥
A quick intro first. We know how our screen look based on the screenshot from avobe. In this “feature” Im using MVVM (check this blog if you wan’t to know how). Let’s focus on the ActorsListFragment
class and see what’s going on…
Very straight forward isn’t it? We render the whole UI in just one place! That’s great! because our tests are going to hit exactly that “place”, the renderUiState
method.
Let’s go to our src/androidTest
directory and create a ActorsListFragmentInstrumentedTest
class. It will look something like this

ActorsListFragmentInstrumentedTest
The first step is to annotate the class with the RunWith(AndroidJUnit4::class)
annotation. We are testing a fragment, how can we launch a fragment without an activity? Thankfully the new fragment testing library comes with helpers for do this, FragmentScenario
allow us to launch a fragment in a incorporated container. If you want to see how does it work, check out this great video! Im sure it’s going to be useful for you
Our main task here is to validate if our views are behaving as we expect when a given state enters to the renderUiState
method, therefore, we don’t need to work with our ViewModel and all the classes it depends directly! Remember the phrase from the previous blog?
As long as your code is clean, your tests are going to be really easy to make
Time to instantiate our variables and prepare our environment, like this
We first create a lateinit var instance of a FragmentScenario
in order to launch our ActorListFragment
in the fragment scenario container (activity). Our fragment, has a dependency on a ViewModel, but we are not going to actually use it, therefore we can just mock it.
Our test is extending AutoCloseKoinTest
in order to load & unload koin modules automatically.
Now we are going to code the actual tests, like this

We use the fragmentScenario.onFragment
block and invoke the renderUiState
method with a custom view State model.
After passing the custom state model that is going to render UI, we are validating our views visibility work as we expect with the help of the espresso
methods.
That’s it. Now you can run the test and it will run on a Emulator or your phone if is connected.
We’ve got the whole actor list screen tested from start to end now. We know that our repository works as we expected, we know that our views are being draw correctly when a given state is passed.
Surprise tip 🎁
Sometimes you will need to share some classes between your unit & instrumented tests. If that is your case, please follow the instructions on this blog in order to create a shared test directory. After doing what the blog says everything inside that directory can be available for your unit & instrumented tests.
Conclusion 🍾
It wasn’t so hard to test and validate if our screen is working as we expect. With the help of unit & instrumented tests running successfully we can be sure that our app is going to have less or none side effect / bug.
So you save valuable time, increase your product effectiveness and have less customers angry for something that don’t work!
Go and explore the espresso
or other libraries and tests your forms, lists, navigation flows & more.
The project can be found here
Don’t forget to leave your claps, stars, comments, improvements, jokes etc! If you want to ask me something DM me and I will get you back as soon as I can.
See you later 👋.