testUI (Jenkins) using espresso

2019-03-11 04:36发布

问题:

The app is passing the espresso tests locally, i mean directly to the devices and genymotion emulators. When I use Jenkins to built an app's image. The espresso test are not successful I get this error.

JENKINS:

 java.lang.RuntimeException: Waited for the root of the view hierarchy to have window focus and not be requesting layout for over 10 seconds. If you specified a non default root matcher, it may be picking a root that never takes focus. Otherwise, something is seriously wrong. Selected Root:
Root{application-window-token=android.view.ViewRootImpl$W@536a97d4, window-token=android.view.ViewRootImpl$W@536a97d4, has-window-focus=false, layout-params-type=1, layout-params-string=WM.LayoutParams{(0,0)(fillxfill) sim=#100 ty=1 fl=#1810100 pfl=0x8 wanim=0x103028f}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=800, height=1184, has-focus=true, has-focusable=true, has-window-focus=false, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}}
. All Roots:
Root{application-window-token=android.view.ViewRootImpl$W@536a97d4, window-token=android.view.ViewRootImpl$W@536a97d4, has-window-focus=false, layout-params-type=1, layout-params-string=WM.LayoutParams{(0,0)(fillxfill) sim=#100 ty=1 fl=#1810100 pfl=0x8 wanim=0x103028f}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=800, height=1184, has-focus=true, has-focusable=true, has-window-focus=false, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}}
at com.google.android.apps.common.testing.ui.espresso.base.RootViewPicker.get(RootViewPicker.java:84)
at com.google.android.apps.common.testing.ui.espresso.ViewInteractionModule.provideRootView(ViewInteractionModule.java:51)
at com.google.android.apps.common.testing.ui.espresso.ViewInteractionModule$$ModuleAdapter$ProvideRootViewProvidesAdapter.get(ViewInteractionModule$$ModuleAdapter.java:187)
at com.google.android.apps.common.testing.ui.espresso.ViewInteractionModule$$ModuleAdapter$ProvideRootViewProvidesAdapter.get(ViewInteractionModule$$ModuleAdapter.java:151)
at com.google.android.apps.common.testing.ui.espresso.base.ViewFinderImpl.getView(ViewFinderImpl.java:52)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction$2.run(ViewInteraction.java:141)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)

回答1:

Stacktrace means that Espresso can't find application window. During testing on emulators screen usually hidden behind Screen Lock. You need use some code to disable ScreenLock programmatically. The most convenient way for me to unlock screen is using Robotium. It has solo.unlockScreen() method. I've put it into setUp() method of testing lifecycle.

Links: https://github.com/RobotiumTech/robotium/blob/master/robotium-solo/src/main/java/com/robotium/solo/Solo.java



回答2:

The solution is to create a custom test runner to unlock the screen and start a wake lock until the tests are done.

public class TestRunner extends android.support.test.runner.AndroidJUnitRunner
{
    private PowerManager.WakeLock mWakeLock;

    @Override
    public void callApplicationOnCreate(Application app)
    {
        // Unlock the screen
        KeyguardManager keyguard = (KeyguardManager) app.getSystemService(Context.KEYGUARD_SERVICE);
        keyguard.newKeyguardLock(getClass().getSimpleName()).disableKeyguard();

        // Start a wake lock
        PowerManager power = (PowerManager) app.getSystemService(Context.POWER_SERVICE);
        mWakeLock = power.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, getClass().getSimpleName());
        mWakeLock.acquire();

        super.callApplicationOnCreate(app);
    }

    @Override
    public void onDestroy()
    {
        mWakeLock.release();

        super.onDestroy();
    }
}

Then AndroidManifest.xml of your tests and add the necessary permissions:

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Don't forget to edit your build.gradle to use the new testInstrumentationRunner class.

Source



回答3:

From my point of view, you need to organize your Jenkins job in the following way: before running Espresso tests (I suppose you have connectedAndroidTest in a gradle post-build action there or something like this), add a post-build action to uninstall the app package and another one to uninstall the app test package. Example: com.example.mypackage.debug and com.example.mypackage.debug.test. This is a good way to refresh the app into your smartphone/emulator, in order to let Espresso use its magic.

Also be sure that you have the Always On option in Developer Tools activated (depending on the device, in Settings you have Developer options or Developer tools submenu).

If none of this work, it means that somewhere in your Jenkins job you have some order of actions issue and need to be clarified. For me the uninstalling of the packages helped me clean the system of all the things related to my app.

Hopefully it will work for you too.

If not, please write comment and I will help you.

Good luck!



回答4:

I suggest using Test-Butler, to disable animation and unlock screen while testing.