2015년 12월 20일 일요일

Android Testing Library


Android testing support library includes the followings:
1) AndroidJunitRunner: JUnit4 compatible test runner for Android
2) Espresso: UI testing framework, suitable for functional UI testing within an app
3) UI Automator: UI testing framework, suitable for cross-app functional UI testing


1) AndroidJunitRunner
- Looks really familiar with Junit, but should avoid mixing JUnit3 and JUnit4
- For use JUnit4, must use @RunWith(AndroidJUnit4.class) annotation


import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnitRunner;
import android.test.ActivityInstrumentationTestCase2;

@RunWith(AndroidJUnit4.class)
public class CalculatorInstrumentationTest
        extends ActivityInstrumentationTestCase2 {

    @Before
    public void setUp() throws Exception {
        super.setUp();

        // Injecting the Instrumentation instance is required
        // for your test to run with AndroidJUnitRunner.
        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
        mActivity = getActivity();
    }

    @Test
    public void typeOperandsAndPerformAddOperation() {
        // Call the CalculatorActivity add() method and pass in some operand values, then
        // check that the expected value is returned.
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }
}



2) Espresso
In order for the Android Plug-in for Gradle to correctly build and run your Espresso tests,
you must specify the following libraries in the build.gradle file of your Android app module:

dependencies {
    androidTestCompile 'com.android.support:support-annotations:23.0.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    androidTestCompile 'com.android.support.test:rules:0.4.1'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    // Set this dependency if you want to use Hamcrest matching
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
}

Steps for writing codes are easy, check the below steps.
- Find the UI component to test in an Activity by calling onView(), onData()
- Simulate a specific user interaction by calling ViewInteraction.perform(), DataInteraction.perform()
- Make sure everything works as expected

// find a view by looking for a text string it displays 
onView(withText("Sign-in"));

// find a view with resource id
onView(withId(R.id.button_signin));

// allOf() combines multiple matchers together
// find a view that has resource id of button_signin and contain the string "Sign-in"
onView(allOf(withId(R.id.button_signin), withText("Sign-in")));

// with not keyword can filter those views do not matchers
// find a view that has resource id of button_signin but do not contain the string "Sign-in"
onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));


In an AdapterView widget, the view is dynamically populated with child views at runtime. If the target view you want to test is inside an AdapterView (such as a ListView, GridView, or Spinner), the onView() method might not work because only a subset of the views may be loaded in the current view hierarchy.

Instead, call the onData() method to obtain a DataInteraction object to access the target view element.
onData(allOf(is(instanceOf(Map.class)),
        hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));


The ViewActions class provides a list of helper methods for specifying common actions. You can perform actions like:
- ViewActions.click(): Clicks on the view.
- ViewActions.typeText(): Clicks on a view and enters a specified string.
- ViewActions.scrollTo(): Scrolls to the view. The target view must be subclassed from ScrollView
- ViewActions.pressKey(): Performs a key press using a specified keycode.
- ViewActions.clearText(): Clears the text in the target view.

Lastly call the ViewInteraction.check() or DataInteraction.check() method to assert that the view in the UI matches some expected state.

// Check that the text was changed.
    onView(withId(R.id.textToBeChanged))
            .check(matches(withText(STRING_TO_BE_TYPED)));


3) UI Automator
In order for the Android Plug-in for Gradle to correctly build and run your UI Automator tests, you must specify the following libraries in the build.gradle file of your Android app module:
dependencies {
    androidTestCompile 'com.android.support:support-annotations:23.0.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
    // Set this dependency if you want to use Hamcrest matching
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
}


// Initialize UiDevice instance
private UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// find Cancel/OK button object
UiObject cancelButton = mDevice.findObject(new UiSelector()
        .text("Cancel"))
        .className("android.widget.Button"));
UiObject okButton = mDevice.findObject(new UiSelector()
        .text("OK"))
        .className("android.widget.Button"));

// Simulate a user-click on the OK button, if found.
if(okButton.exists() && okButton.isEnabled()) {
    okButton.click();
}


// With UiSelector, it is possible to access a specific UI component in an app
// the first list view in the currently displayed UI
// then find UI element with the text property "Apps"
UiObject appItem = new UiObject(new UiSelector()
        .className("android.widget.ListView")
        .instance(1)
        .childSelector(new UiSelector()
        .text("Apps")));

Once your test has obtained a UiObject object, you can call the methods in the UiObject class to perform user interactions on the UI component
represented by that object. You can specify such actions as:

- click(): Clicks the center of the visible bounds of the UI element.
- dragTo(): Drags this object to arbitrary coordinates.
- setText(): Sets the text in an editable field, after clearing the field's content.
- swipeUp(): Performs the swipe up action on the UiObject.
Similarly, the swipeDown(), swipeLeft(), and swipeRight() methods perform corresponding actions.


Lastly use standard JUnit Assert methods to test that UI components in the app return the expected results.

private static final String CALC_PACKAGE = "com.myexample.calc";

public void testTwoPlusThreeEqualsFive() {
    // Enter an equation: 2 + 3 = ?
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("two")).click();
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("plus")).click();
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("three")).click();
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("equals")).click();

    // Verify the result = 5
    UiObject result = mDevice.findObject(By.res(CALC_PACKAGE, "result"));
    assertEquals("5", result.getText());
}


Reference:
Android Testing Support Library

댓글 없음:

댓글 쓰기