Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.linkedin:test-butler:2.2.1'
}
dependencies {
implementation("com.github.linkedin:test-butler:2.2.1")
}
<dependency>
<groupId>com.github.linkedin</groupId>
<artifactId>test-butler</artifactId>
<version>2.2.1</version>
</dependency>
libraryDependencies += "com.github.linkedin" % "test-butler" % "2.2.1"
:dependencies [[com.github.linkedin/test-butler "2.2.1"]]
Reliable Android testing, at your service.
Test Butler was inspired by the Google presentation "Going Green: Cleaning up the Toxic Mobile Environment". For more background, read the Test Butler announcement blog post.
Locale
object for their application to simulate running the app in another language.Test Butler is a two-part project. It includes an Android library that your test code can depend on, as well as a companion Android app apk that must be installed on your Android emulator before using Test Butler. You can build the Test Butler APK yourself from source, or download the binary from Maven Central
The Test Butler library is a thin wrapper around an AIDL interface to give your tests a safe way to talk to the Test Butler app's service running in the background on the emulator.
The Test Butler app is signed using the system keystore for the Android emulator, so it is automatically granted signature
-level permissions when installed. This means granting permissions via adb is not necessary. It also means that this app can only be installed on emulators that use the stock Android keystore!
Being a system app makes Test Butler much easier to use than existing Android solutions for changing emulator settings. To disable animations, you just need a single line of code in your app; no extra permissions in your debug manifest, no granting permissions via adb, no Gradle plugin to integrate.
Test Butler can even use permissions that can't be granted via adb, like the SET_ACTIVITY_WATCHER
permission, which lets Test Butler disable crash & ANR dialogs during tests.
Only a few:
Test Butler helper app requires an emulator image with stock Android else it won't install, therefore it will not work with non-stock emulator images such as ones with Google APIs or Google Play!
Test Butler adds a custom IActivityController
to the system to be able to suppress crash & ANR dialogs. This technique is also used internally by the Monkey
tool. Unfortunately, the implementation of the isUserAMonkey()
method takes advantage of the fact that the Monkey
class is the only thing inside Android that sets an IActivityController
and returns true whenever one is set.
This means that isUserAMonkey()
will return true while Test Butler is running! If your app uses this method to invoke different behavior during actual monkey testing, you may encounter issues while running tests with Test Butler. An easy fix is to create a helper method in your app to call instead of isUserAMonkey()
, which returns false
while instrumentation tests are running and calls through to the real isUserAMonkey()
when the app is not being instrumented.
Download the latest .apk and .aar via Maven:
<dependency>
<groupId>com.linkedin.testbutler</groupId>
<artifactId>test-butler-library</artifactId>
<version>2.2.1</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.linkedin.testbutler</groupId>
<artifactId>test-butler-app</artifactId>
<version>2.2.1</version>
<type>pom</type>
</dependency>
or Gradle:
androidTestImplementation 'com.linkedin.testbutler:test-butler-library:2.2.1'
androidTestUtil 'com.linkedin.testbutler:test-butler-app:2.2.1'
You can also download the apk file manually from Maven Central if you prefer.
Install the Test Butler apk on your emulator prior to running tests, then add the following to your test runner class:
public class ExampleTestRunner extends AndroidJUnitRunner {
@Override
public void onStart() {
TestButler.setup(getTargetContext());
super.onStart();
}
@Override
public void finish(int resultCode, Bundle results) {
TestButler.teardown(getTargetContext());
super.finish(resultCode, results);
}
}
To change settings on the device from your tests, just use the methods in the TestButler
class. For example:
@Before
public void setup() {
TestButler.setLocationMode(Settings.Secure.LOCATION_MODE_OFF);
}
@Test
public void verifyBehaviorWithNoLocation() {
// ...
}
@After
public void teardown() {
TestButler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
}
NB: See gotchyas above to see why @BeforeClass
& @AfterClass
aren't used here.
You can use snapshot builds to test the latest unreleased changes. A new snapshot is published after every merge to the main branch by the Deploy Snapshot Github Action workflow.
Just add the Sonatype snapshot repository to your Gradle scripts:
repositories {
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
You can find the latest snapshot version to use in the gradle.properties file.