Android Espresso, Wake up device before test. How to use a custom manifest for test?

Matt Wolfe picture Matt Wolfe · Nov 9, 2013 · Viewed 8.6k times · Source

I've been writing tests with androids new espresso framework and find that it works well. One annoying thing (not particular to espresso) is that I have to make sure my screen is awake and unlocked for the tests to run. I found a workaround (through various sources) however I am not sure the best way to integrate it.

So this is what I did, in my "Home" activity I have the following code:

Home.class:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /************ Put this in a conditional for a test version ***********/
    KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("TAG");
    keyguardLock.disableKeyguard();
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

Also you need to add the following permissions:

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

So after doing this my tests now wake my phone up to run so I don't have to stand guard and make sure that the screen doesn't turn off right before the tests start.

I would rather not include those permissions though in my app obviously. I know with gradle it is possible to make different "flavors" that have their own android manifest which will merge into the main manifest. I was thinking of using that but I'd rather not add a flavor just for that reason given this is already using the test build type to run. It looks like from the android gradle documentation that you can't create an AndroidManifest for the instrumentTest directory as it will be auto generated.

However I was wondering if there is another way to do it without creating a variant and then specifying that the tests should run that variant. Also I'm not sure of the exact syntax of all that and thought it would be nice just to have this information on the site for others as it seems to be scattered about.

Lastly, if anyone knows of a better way of solving the issue of waking the phone up for the tests I'd love to hear it as I'm not a big fan of this way I'm attempting.

Answer

Matt Wolfe picture Matt Wolfe · Nov 13, 2013

I actually figured out a really easy way to handle this. Remove the keyguard and wakelock permissions from the main manifest and put them in src/debug/AndroidManifest.xml like so:

src/debug/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
</manifest>

When the app is built for debug the above permissions will merge into the main manifest. By default the build system uses the debug build for instrument tests so this works fine.

Then in my onCreate I put the code mentioned in the question:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (BuildConfig.DEBUG) {
        KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("TAG");
        keyguardLock.disableKeyguard();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }
    ...
}

Now my phone can run tests without me waking them up by hand first and I didn't have to add the above permissions to the release version of my app.