- Many of the Espresso tests will map to Appium
- e.g.)
Would map to something like
onView(withId(R.id.name_field)) .perform(typeText("Steve"));
findElementByName('name_field').sendKeys('Steve');
- e.g.)
- Make use of https://github.com/JakeWharton/okhttp-idling-resource or something like it to know when resources idling
- Recommend to turn off System Animations
- Run an instance of WebDriver and run espresso queries
- Do we have to choose between Espresso and UIAutomator? Maybe not.
- Espresso waits for UI Events to complete before it moves to next part of test
- How do we switch between apps and processes?
- Need separate instance of Espresso for different processes.
- We need to test if we can:
- Run an HTTP server on an app
- Write test suites that run Espresso tests on arbitrary apps
How to run an espresso testcase from the command line:
adb shell am instrument -w -r -e debug false com.example.android.testing.espresso.BasicSample.test/android.support.test.runner.AndroidJUnitRunner
UiControllerinterface has methods likeinjectKeyEventandinjectMotionEventwhich allow building arbitrary actionsEspressoKey.Builderfor building key codes with meta statesGeneralClickActionfor taking tapper, coordinates, and precision and getting a click actionGeneralSwipeActionKeyEventActionfor turning EspressoKey into an actionMotionEventsfor sending events to a UiController. Events include up, down, move, and cancelReplaceTextActionfor setting value of an EditTextScrollToActionTypeTextAction(includes option for tapping to focus)- Pre-baked
ViewActions:clearTextclickcloseSoftKeyboarddoubleClicklongClickpressBackpressImeActionButtonpressKeypressMenuKeyreplaceTextscrollToswipeDownswipeLeftswipeRightswipeUptypeTexttypeTextIntoFocusedView
ViewMatchershasContentDescriptionhasDescendanthasSibling(matches based on sibling)isCheckedisClickableisCompletelyDisplayedisDescendantOfAisDisplayedisEnabledisFocusableisNotCheckedisRootisSelectedwithChildwithClassNamewithContentDescriptionwithHintwithId(need to use ResourceName instead since string)withInputTypewithParentwithResourceNamewithSpinnerTextwithTagKeywithTagValuewithText
UiController(android.support.test.espresso.UiController): an interface for base-level UI operations. Note that there is a restriction such that these injected events can only interact with the AUT, not other apps.injectKeyEvent(could be useful for sending non-standard keys)injectMotionEvent(for swipes, gestures, etc)injectString(series of key events)
ViewAction(android.support.test.espresso.ViewAction): an interface for performing interactions with view elementsperform
ViewAssertion(android.support.test.espresso.ViewAssertion): an interface for making assertions on viewscheck
ViewFinder(android.support.test.espresso.ViewFinder): an interface for finding viewsgetView(finds a single view within the hierarchy; throws if multiple views or no views are found)
Espresso(android.support.test.espresso.Espresso)closeSoftKeyboardonData(creates a DataInteraction)onView(creates a ViewInteraction)openActionBarOverflowOrOptionsMenuopenContextualActionModeOverflowMenupressBack
ViewInteraction(android.support.test.espresso.ViewInteraction): primary interface for providing action or assert on a viewcheckperforminRoot(scope the ViewInteraction to the root selected by a given root matcher)
LayoutMatchers(android.support.test.espresso.matcher.LayoutMatchers)hasEllipsizedText(matches text views which have elided text)hasMultilineText(matches multiline text views)
RootMatchers(android.support.test.espresso.matcher.RootMatchers)isDialog(matches roots which are dialogs)isFocusableisPlatformPopupisTouchablewithDecorView
ViewMatchers(android.support.test.espresso.matcher.ViewMatchers)hasContentDescriptionhasDescendanthasErrorText(matches EditText based on error string value)hasFocushasImeActionhasLinkshasSibling(matches based on sibling)isCheckedisClickableisCompletelyDisplayedisDescendantOfAisDisplayedisDisplayingAtLeastisEnabledisFocusableisJavascriptEnabled(for webviews)isNotCheckedisRootisSelectedsupportsInputMethodswithChildwithClassNamewithContentDescriptionwithEffectiveVisibilitywithHintwithId(need to use ResourceName instead since string)withInputTypewithParentwithResourceNamewithSpinnerTextwithTagKeywithTagValuewithText
DrawerActions(android.support.test.espresso.contrib.DrawerActions)closeopen
DrawerMatchers(android.support.test.espresso.contrib.DrawerMatchers)isClosedisOpen
NavigationViewActions(android.support.test.espresso.contrib.NavigationViewActions)navigateTo(navigate to a menu item using a menu item resource id)
PickerActions(android.support.test.espresso.contrib.PickerActions)setDatesetTime
RecyclerViewActions(android.support.test.espresso.contrib.RecyclerViewAction)actionOnHolderItemactionOnItemactionOnItemAtPositionscrollToscrollToHolderscrollToPosition
ActiveRootLister(android.support.test.espresso.base.ActiveRootLister)listActiveRoots(could be nice for building XML?)
RootViewPicker(android.support.test.espresso.base.RootViewPicker)get(gets the root view of the top-most window with which the user can interact)
EspressoKey.Builderfor building key codes with meta statesGeneralClickActionfor taking tapper, coordinates, and precision and getting a click actionGeneralSwipeActionKeyEventActionfor turning EspressoKey into an actionMotionEventsfor sending events to a UiController. Events include up, down, move, and cancelReplaceTextActionfor setting value of an EditTextScrollToActionTypeTextAction(includes option for tapping to focus)
- Resign with the same certificate as the test runner will be signed
- Install
apktool d app-debug-androidTest.apk- edit
AndroidManifest.xmlto set the instrumentationandroid:targetPackageto the package for the AUT apktool b app-debug-androidTest -o a.apkzipalignthea.apkfile (zipalign -v -p 4 a.apk a-aligned.apk)- sign the aligned file (
apksigner sign --ks my-release-key.jks --out a-release.apk a-aligned.apk) - remove the old runner (
adb uninstall io.appium.espresso.BasicSample.test) - install the new runner (
adb push a-release.apk /data/local/tmp/io.appium.espresso.BasicSample.test && adb shell pm install -t -r "/data/local/tmp/io.appium.espresso.BasicSample.test")
Within the test the package/activity that is passed in can be launched:
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
// ...
final String CLASS_NAME = "io.appium.android.apis.ApiDemos";
Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
ActivityMonitor mSessionMonitor = mInstrumentation.addMonitor(CLASS_NAME, null, false);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName(i.getTargetContext(), CLASS_NAME);
mInstrumentation.startActivitySync(intent);
Activity mCurrentActivity = mInstrumentation.waitForMonitor(mSessionMonitor);
assertNotNull(mCurrentActivity);adb shell am instrument -w -r -e debug false io.appium.espresso.BasicSample.test/android.support.test.runner.AndroidJUnitRunner