Android UI Test with WebView

Android UI Test

These days, Espresso covers a lot of UI Test features.
And Espresso covers WebView contents assertion with espresso-web.

It’s nice to test WebView base application.
In this entry, I want to explain

Preparation

Before staring, we add some dependencies for espresso and espresso web
build.gradle

android {
    defaultConfig {
        
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    packagingOptions {
        exclude 'META-INF/maven/com.google.guava/guava/pom.properties'
        exclude 'META-INF/maven/com.google.guava/guava/pom.xml'
    }

I added testInstrumentationRunner and packagingOptions.
testInstrumentationRunner is for UnitTest annotation.
packagingOptions is to solve build problem.

dependencies {
  compile 'com.android.support:support-annotations:23.1.1'
  androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
  androidTestCompile 'com.android.support.test:runner:0.5'
  androidTestCompile 'com.android.support.test:rules:0.5'
  androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2'
}

I added above libraries

Now you can resolve dependencies to start Test.

UI Test

Espresso : Google Developer

There are a lot of test methods

WebView Test

Espresso Web covers WebView based application test. You can detect DOM using API.
Documentation : Espresso Web

We can get WebView controller and verify by DOM.

Sample

This example tests small web service.
Press button and open WebView and check contents (This is virtual test and it doesn’t work as it is).

ButtonIdlingResource
This class is helper to wait until button becomes enables.
In this example, button becomes when the service is ready.

public ButtonIdlingResource implements IdlingResource {
  
  private ResourceCallback resourceCallback;
   
  private Button button;

  public PortalButtonIdlingResource(PortalButton button) {
    this.button = button;
  }

  @Override
  public String getName() {
      return ButtonIdlingResource.class.getName();
  }

  @Override
  public boolean isIdleNow() {
      boolean idle = this.button.isEnabled();
      if (idle && resourceCallback != null) {
          resourceCallback.onTransitionToIdle();
      }
      return idle;
  }

  @Override
  public void registerIdleTransitionCallback(ResourceCallback callback) {
      this.resourceCallback = callback;
  }
}

Test code(ExpressoTest.java)
Steps of this code.

@RunWith(AndroidJUnit4.class)
@LargeTest
public class EspressoTest {

    private Activity activity;

    @Rule
    public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule(MainActivity.class);

    @Before
    public void setUp(){
        this.activity = activityTestRule.getActivity();
    }

    @Test
    public void serviceTest() {
         Button button = (Button)activity.findViewById(R.id.button1);   // Retrieve Button from layout

         // Wait until the target button becomes enable
         IdlingResource idlingResource = new PortalButtonIdlingResource(button);
         Espresso.registerIdlingResources(idlingResource);

         // Find button and click(you have several choices to find UI from Activity)
         Espresso.onView(ViewMatchers.withClassName(Matchers.equalToIgnoringCase("android.widget.Button"))).perform(ViewActions.click());
         Espresso.unregisterIdlingResources(idlingResource);


         // If you can click button, new activity is displayed and webview will start loading.
          Web.onWebView().check(WebViewAssertions.webContent(DomMatchers.containingTextInBody("Android")));   // Check WebView body
    }
    
}

Now, ready to start test.
The way of running is same as app.

WebView.onWebView().check waits until page is loaded.