State clearing
This question appears as soon as you need to run more than 1 ui test.
Problem
We run Test1
, it performs some http requests, saves some data to files and databases.
When Test1
is finished, Test2
will be launched.
However, Test1
left some data on the device which can be a reason of Test2
failing.
Solution — clear the data before each test
1. Clearing within a process
In this case, we don't kill our application process, and we have 2 options here:
Use component from a real code base
@Before
fun setUp() {
DI.provideLogoutCleanerInteractor().clear()
}
The same component which clears data (For instance, while logout). It should honestly clear everything in your application: Databases, Files, Preferences and Runtime cache, and should be executed before each test.
Danger
This solution is a bottleneck and it's better to avoid it at all. If LogoutCleaner is broken, all of the tests will be failed.
Clear internal storage
All cache in an android application is stored in the internal storage: /data/data/packagename/
This storage is our application sandbox and can be accessed without any permission.
Basic idea is to avoid using components from a real code base. Instead of them, use some tests rules which do the job for us.
@get:Rule
val clearPreferenceRule = ClearDatabaseRule()
@get:Rule
val clearFilesRule = ClearFilesRule()
@get:Rule
val clearFilesRule = ClearPreferencesRule()
They have already been implemented in Barista library, you can find them here
Warning
This solution won't in 100% of cases:
- You may have runtime cache, which can also affect your tests
- Test or application process may crash and prevent the launch of next tests
Conclusion
These are pros/cons for both solutions which don't kill the process:
➕ Fast implementation
➕ Fast execution in the same process
➖ Don't give you any guarantee that your app will be cleared properly
➖ Application or Test process killing will break tests execution
➖ Can be a bottleneck
Use these solutions only as a temp workaround, because it won't work on perspective in huge projects
2. Clearing package data
Our aim is to simulate the same behavior as when user presses the clear data
button in application settings.
Application process will be cleared in that case, our application will be started in a cold start.
Orchestrator
Basically, you can achieve an isolated state, if you execute your tests like this:
adb shell am instrument -c TestClass#method1 -w com.package.name/junitRunnerClass
adb pm clear
adb shell am instrument -c TestClass#method2 -w com.package.name/junitRunnerClass
adb pm clear
Each test should be executed in an isolated instrumented process and junit reports should be merged into a big one report when all tests are finished.
That's the common idea of Orchestrator
.
It's just an apk
which consist of
only several classes
and runs tests and clears data, as described above.
You should install an orchestrator
along with application.apk
and instrumented.apk
on the device.
However, it's not the end.
Orchestrator should somehow execute adb commands. Under the hood, it
uses special services.
It's just a shell client and should be installed to the device.
An official documentation and guide how to start with Orchestrator
Warning
Despite the fact that it does the job, this solution looks overcomplicated:
- We need to install +2 different apk to each emulator
- We delegate this job to the device instead of host machine.
Devices are less reliable than host pc
Other solutions
It's also possible to clear package data by using 3rd party test runners, like Marathon, Avito-Runner or Flank. Marathon and Avito-Runner clear package data without an orchestrator. They delegate this logic to a host machine
Conclusion
These are pros/cons for an orchestrator
and 3rd party test runners solution:
➕ Does the job for us in 100%
➖ Slow execution (can take 10+ seconds and depends on apk size)
➖ Orchestrator — over-complicated
Each adb pm clear
takes some time and depends on apk size. Below you may see some gaps between the tests which
represent such a delay
Success
Only package clear can guarantee that your data will be celared properly. Marathon and Avito-Runner provide the easiest way to clear application data.
- You can set them just by one flag in configuration
- They don't use orchestrator under the hood