4

What is the correct mechanism to deal with Interstitial Ad during Espresso Tests?

There is Interstitial Ad between two activities and I want to write an Espresso Test spanning both activities.

Is there any way to close the Interstitial Ad during Espresso test to continue testing second Activity?

Can it be done using Espresso-Intents?

OR

Is the Mix of UIAutomator tests and Espresso the only solution to this problem?

enter image description here

PunitD
  • 2,293
  • 1
  • 20
  • 29
  • Any luck with this? I'm stuck here too. – Matej Aug 31 '16 at 10:11
  • I guess there is no straightforward way to run Espresso tests involving the library UI(in this case google admob) in between activities..In my case it was free and paid flavor thing..I used to display Ad in 'free' flavor in between two activities and not in 'paid' one ..so in case of Free flavor, i used to test whether UI elements on next screen are visible when i click on some element in first screen which takes user to second screen..If they are visible then test should fail and vice-versa tests for 'paid' version case..makes sense? Any suggestions to improve this? – PunitD Aug 31 '16 at 16:07
  • 1
    Maybe you could use the UI automator, and press the system back button using it, and close the interstitial this way. Anyway, I gave up since I was pressed for time and Espresso ironically proved to be more flaky for me than Robotium, so I instead used that with a little bit of custom waiting logic, and it worked straight away. – Matej Aug 31 '16 at 16:11
  • Did you find the solution to this? – Damia Fuentes Sep 28 '17 at 08:29
  • @DamiaFuentess I don't remember what i did back then. Mostly i implemented what i have written in above comment. I'll check source code and get back to you. – PunitD Oct 02 '17 at 06:41

5 Answers5

2

I had the problem too just recently, so I just used the Espresso Test Recorder to record my close ad to see what the test record does, it just uses the following:

    ViewInteraction imageButton = onView(
            allOf(withContentDescription("Interstitial close button"), isDisplayed()));
    imageButton.perform(click());

Works for now, but I don't know if this would work for future adMob libs and certainly won't work after they change the content description.

For future reference, I'm using version 11.0.4 ads library:

freeCompile 'com.google.android.gms:play-services-ads:11.0.4'
Andrew Lam
  • 1,371
  • 17
  • 35
1

Add this library to your gradle:

androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'

Then in your Espresso test after you ad is shown:

Thread.sleep(5000); // Necessary time you needed to show your ads, for example 5 seconds

// After that, press back button to go back
UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        mDevice.pressBack();

If your app runs on SDK level lower than 18 create another AndroidManifest.xml file in your test directory src/androidTest/ with this code so your tests will run with minSdkVersion=18 (which is the API level needed for UIAutomator):

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="com.monkingme.monkingme"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-sdk
        android:minSdkVersion="18"
        tools:overrideLibrary="android.support.test.uiautomator.v18" />
</manifest>
Damia Fuentes
  • 5,308
  • 6
  • 33
  • 65
0

What is the correct mechanism to deal with Interstitial Ad during Espresso Tests?

There is Interstitial Ad between two activities and I want to write an Espresso Test spanning both activities.

Is there any way to close the Interstitial Ad during Espresso test to continue testing second Activity?

IMO, the correct solution is to setup your tests so they don't need to span multiple activities.

Tests should be focused and isolated. You don't need to span Activities to assert behavior because there is a logical separation at the transition point. So instead of writing a test that says "doing x in Activity A should open Activity B in state y, and doing z in Activity B should do this or that", you write multiple tests:

1) "doing x in Activity A should launch an intent to open Activity B" (you don't care about the UI state or your ad), which you can easily verify with the Intents API.

2) "launching Activity B with a given Intent (which is what you expect from the transition from A to B) should initialize it to state y", which you can easily set up by passing an Intent to your activity rule and using matchers on the UI.

3) "doing z in Activity B when started with state y should do this or that", which you can easily verify by starting the activity as in (2).

Hope that helps.

dominicoder
  • 9,338
  • 1
  • 26
  • 32
0

In my case, the suggested answers didn't work. So this is my solution.

try {
     onView(withContentDescription("Interstitial close button")).check(matches(isEnabled()))
     onView(isRoot()).perform(ViewActions.pressBack())
    } catch (e: NoMatchingViewException) {
    }

Checking if the ad exists and if so - click on the back button.

Idan Magled
  • 2,186
  • 1
  • 23
  • 33
0

Create your own ViewAction class without view visibility constraints:

public static ViewAction myClick() {

return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
        return ViewMatchers.isEnabled(); // no constraints, they are checked above
    }

    @Override
    public String getDescription() {
        return null;
    }

    @Override
    public void perform(UiController uiController, View view) {
        view.performClick();
    }
};

}

Then to use it:

onView(withContentDescription("Interstitial close button")).perform(myClick());

This way ad will be closed automatically. Also, animations have to be disabled in the developers settings.

MarcinBLN
  • 39
  • 4