This is a project to demonstrate how screenshot testing works and how to setup and configure in your project.
Take a look at the documentation at http://facebook.github.io/screenshot-tests-for-android/#getting-started and https://github.com/Karumi/Shot
- Install Python
- Set Android-Sdk and python paths (or for Windows set Environments Variables)
- Upgrade pip
pip -m pip install --upgrade pip - Install Pillow
pip install Pillow
Setup the Gradle plugin:
buildscript {
// ...
dependencies {
// ...
classpath 'com.karumi:shot:2.2.0'
}
}
apply plugin: 'shot'
shot {
appId = 'YOUR_APPLICATION_ID'
}This plugin sets up a few convenience commands you can list executing ./gradlew tasks and reviewing the Shot associated tasks:
If you are using flavors update your shot configuration inside the build.gradle file as follows:
shot {
appId = 'YOUR_APPLICATION_ID'
instrumentationTestTask = 'connected<FlavorName><BuildTypeName>AndroidTest'
packageTestApkTask = 'package<FlavorName><BuildTypeName>AndroidTest'
}The screenshots library needs the WRITE_EXTERNAL_STORAGE permission.
If your app already has the permission then nothing needs to be done.
But if your app does not have it then there are two ways to do it:
- You can create an
AndroidManifest.xmlfile inside theandroidTestfolder but make sure that your mainAndroidManifest.xmland the one in theandroidTesthave the samesharedUserId
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="<YOUR_APP_ID>.test"
android:sharedUserId="<YOUR_APP_ID>.uid">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>- You can create a
debugfolder insrcand inside it you can create anAndroidManifest.xmlwhich will have the permission.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="<YOUR_APP_ID>">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>Also remember to configure the instrumentation test runner in your build.gradle as follows:
android {
// ...
defaultConfig {
// ...
testInstrumentationRunner "<YOUR_APP_ID>.<PATH_TO_FILE>.ScreenshotTestRunner"
}
In order to do this, you'll have to create a class named ScreenshotTestRunner, like the following one, inside your instrumentation tests source folder:
public class ScreenshotTestRunner extends AndroidJUnitRunner {
@Override
public void onCreate(Bundle args) {
ScreenshotRunner.onCreate(this, args);
super.onCreate(args);
}
@Override
public void finish(int resultCode, Bundle results) {
ScreenshotRunner.onDestroy();
super.finish(resultCode, results);
}
}In order to be able to record/verify among different machines then you need to setup the same emulator on all machines
You can do it the classic way from the Android Studio or by running the avdmanager command:
avdmanager create avd -f -n <name> -k <"image"> -c <size> -d <id>and an example of it is:
avdmanager create avd -n screenshot_tester -k "system-images;android-21;default;armeabi-v7a" -c 100M -f -d 22@Test
fun theActivityIsShownProperly() {
val mainActivity = startMainActivity()
/*
* Take the actual screenshot. At the end of this call, the screenshot
* is stored on the device and the gradle plugin takes care of
* pulling it and displaying it to you in nice ways.
*/
Screenshot.snapActivity(activity).record()
}According to the Android version you will choose for your emulator you may have issues with permission granting.
In order to solve this you can add a library and use the GrantPermissionRule in your test class.
Add com.android.support.test:rules:1.1.0 or androidx.test:rules:1.1.0(if you migrated to AndroidX) in your app's build.gradle file.
Then add:
@JvmField
@Rule
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)or in java
@Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);You can record your screenshot tests executing this command:
./gradlew executeScreenshotTests -PrecordThis will execute all your integration tests and it will pull all the generated screenshots into your repository so you can easily add them to the version control system.
Once you have a bunch of screenshot tests recorded you can easily verify if the behaviour of your app is the correct one executing this command:
./gradlew executeScreenshotTestsAfter executing your screenshot tests using the Gradle task executeScreenshotTests a report with all your screenshots will be generated.
You can run a single test or test class, just add the android.testInstrumentationRunnerArguments.class parameter within your gradle call. This option works for both modes, verification and recording, just remember to add the -Precord if you want to do the latter.
Running all tests in a package:
./gradlew executeScreenshotTests -Pandroid.testInstrumentationRunnerArguments.package=com.your.packageRunning all tests in a class:
./gradlew executeScreenshotTests -Pandroid.testInstrumentationRunnerArguments.class=com.your.package.YourClassTestRunning a single test:
./gradlew executeScreenshotTests -Pandroid.testInstrumentationRunnerArguments.class=com.your.package.YourClassTest#yourTest