35

enter image description here

@Test
    public void test3_PaySuccessful(){
        init();

    ViewInteraction amountEditText = onView(
            allOf(withId(R.id.et_amount), isDisplayed()));
    amountEditText.perform(replaceText("SGD 0.010"), closeSoftKeyboard());

    //, withText("Proceed")
    ViewInteraction appCompatButton = onView(
            allOf(withId(R.id.btn_confirm), isDisplayed()));
    appCompatButton.perform(click());

    //, withText("Pay")
    ViewInteraction appCompatButton2 = onView(
            allOf(withId(R.id.btn_confirm), isDisplayed()));
    appCompatButton2.perform(click());

    //dialog
    ViewInteraction appCompatButton3 = onView(
            allOf(withId(R.id.confirm_button), withText("Confirm"), isDisplayed()));
    appCompatButton3.perform(click());

    //have to disable animation in order to pass this.
    intended(CoreMatchers.allOf(hasComponent(PaymentSelectionActivity2.class.getName())));

}

I encountered an issue on doing Espresso testing with a view involving animation, I know Espresso cannot deal with animation, so i did below. - disable my test device Window animation, transition animation and animator duration scale all set to OFF (this does not work) - then i tried to add a flag in my code eg. espresso_testing = true. if true, my code will skip calling all startAnimation() function call. ---> this is working. However, there is a requirement that I cannot change code on my app while writing espresso test case. Included a test case above.

Is there any other way to do this? Thanks in advance.

kggoh
  • 742
  • 1
  • 10
  • 24

4 Answers4

99

Make sure to keep your plugin updated:

buildscript {
  repositories {
    google()
    gradlePluginPortal()
  }

  dependencies {
    classpath 'com.android.tools.build:gradle:3.3.0'
  }
}

Use the new flag in testOptions called animationsDisabled:

android {

  ...

  testOptions {
    animationsDisabled = true
  }
}

Source: https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.TestOptions.html#com.android.build.gradle.internal.dsl.TestOptions:animationsDisabled

You can try turning off animations on your device/emulator manually:

To avoid flakiness, we highly recommend that you turn off system animations on the virtual or physical devices used for testing. On your device, under Settings > Developer options, disable the following 3 settings:

Window animation scale Transition animation scale Animator duration scale

Source: https://developer.android.com/training/testing/espresso/setup#set-up-environment

You can try using adb via command line:

# Turn off animations
adb shell settings put global window_animation_scale 0 &
adb shell settings put global transition_animation_scale 0 &
adb shell settings put global animator_duration_scale 0 &

Source: https://github.com/jaredsburrows/android-gif-example/blob/master/.travis.yml#L34

You can try LinkedIn's TestButler:

TestButler.verifyAnimationsDisabled(InstrumentationRegistry.getTargetContext());

Source: https://github.com/linkedin/test-butler/blob/master/test-butler-demo/src/androidTest/java/com/linkedin/android/testbutler/demo/AnimationDisablerTest.java#L26

You can try creating a TestRule and Gradle task for your espresso tests:

Source: https://product.reverb.com/disabling-animations-in-espresso-for-android-testing-de17f7cf236f

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
  • I am using a real device for testing, does the above still apply? – kggoh May 09 '17 at 04:44
  • @kggoh You can try the Android DSL `animationsDisabled`, the second one may or may not work. I use it on API 19 emulators. – Jared Burrows May 09 '17 at 04:47
  • animationsDisabled is unknown property and i did add the buildscript you stated above – kggoh May 09 '17 at 04:54
  • 2
    `animationsDisabled` is not an unknown property. I just pointed you to the official documentation. You have to have the latest android plugin `2.3.1`. – Jared Burrows May 09 '17 at 05:02
  • 4
    @JaredBurrows, have you tested `animationsDisabled` flag on your own or are you just relying on documentation? Personally I am unable to make use of that flag, – azizbekian Sep 05 '17 at 11:31
  • @azizbekian I relied on documentation but I try to use all techniques. If you are using Spoon or TestButler, you can toggle off animations as well. – Jared Burrows Sep 05 '17 at 20:02
  • 2
    For others: `animationsDisabled` is equivalent of `am instrument --no-window-animation` for running tests and `adb shell settings put global window_animation_scale 0` before running tests. To disable all animations run all three `adb shell ...` commands from above answer before running tests. Source: https://issuetracker.google.com/issues/69247502 – R. Zagórski Mar 05 '18 at 13:08
  • Do these settings apply to Lottie animations? Seems like some of our Lottie animations continue to run in UI tests. – fobo66 Jan 30 '19 at 11:23
  • 1
    `animationsDisabled` doesn't work according to http://myhexaville.com/2018/01/15/android-espresso-testing/ and according to my experience just now with gradle-5.1.1-all.zip and com.android.tools.build:gradle:3.4.0. – Michael Osofsky Aug 08 '19 at 18:07
  • 1
    Note the documentations says ["This property does not affect tests that you run using Android Studio."](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/TestOptions#animationsdisabled) – Michael Osofsky May 13 '21 at 18:12
  • @Michael Osofsky True, but starting from Android Studio Bumblebee instrumented tests are executed via Gradle test runner – Derek K Jan 29 '22 at 11:05
7

You have three different options to choose from:

1. Use this in Gradle

android {

  //...

  testOptions {
    animationsDisabled = true
  }

  // ...
}

2. Use in ADB for device

adb shell settings put global window_animation_scale 0 &
adb shell settings put global transition_animation_scale 0 &
adb shell settings put global animator_duration_scale 0 &

3. Use the Rule

class DisableAnimationsRule : TestRule {
    override fun apply(base: Statement, description: Description): Statement {
        return object : Statement() {
            @Throws(Throwable::class)
           override fun evaluate() {
                // disable animations for test run
                changeAnimationStatus(enable = false)
                try {
                    base.evaluate()
                } finally {
                    // enable after test run
                    changeAnimationStatus(enable = true)
                }
            }
        }
    }

    @Throws(IOException::class)
    private fun changeAnimationStatus(enable:Boolean = true) {
        with(UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())){
            executeShellCommand("settings put global transition_animation_scale ${if(enable) 1 else 0}")
            executeShellCommand("settings put global window_animation_scale ${if(enable) 1 else 0}")
            executeShellCommand("settings put global animator_duration_scale ${if(enable) 1 else 0}")
        }
    }
}
Den Drobiazko
  • 1,077
  • 1
  • 13
  • 33
Rasoul Miri
  • 11,234
  • 1
  • 68
  • 78
  • 3
    The way you list points makes it look like one **has to** do all those steps to disable animations but in fact they are all alternative of each other. That is why adding description is helpful – Farid Jul 05 '22 at 06:23
5

True, you shouldn't add test code in production code. The problem here lies in the animation. If you are performing animations using Handlers and Runnables then you can't turn them off using the Developer Options. A common place where we use this to animate is in Custom views.

But even in custom views, ensure you use either ValueAnimator, ObjectAnimator or AnimatorSet to perform your animation. Only then you can turn off animations by turning off Animator duration scale in Developer options.

A good reference is the ProgressBar.

Henry
  • 17,490
  • 7
  • 63
  • 98
2

You could take a look at this repo

Build the project and download the generated .apk file and follow the instructions mentioned in that project to disable the animations and you should have a smooth sailing afterwards. You could also download the same .apk file from a lot of other sources. Once you have the .apk file then issue the following commands:

adb install -r android_emulator_hacks.apk
adb shell pm grant no.finn.android_emulator_hacks android.permission.SET_ANIMATION_SCALE
adb shell am start -n no.finn.android_emulator_hacks/no.finn.android_emulator_hacks.HackActivity

This will take care of disabling the system animations for you.

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
mark w.
  • 1,047
  • 9
  • 16