1*ae5b1ec8SZiwei Zhang# Espresso Snippet Example 2*ae5b1ec8SZiwei Zhang 3*ae5b1ec8SZiwei ZhangThis tutorial shows you how to create snippets that automate the UI of another 4*ae5b1ec8SZiwei Zhangapp using Espresso. 5*ae5b1ec8SZiwei Zhang 6*ae5b1ec8SZiwei ZhangThe same approach can be used to create any snippet app that needs to access 7*ae5b1ec8SZiwei Zhangthe classes or resources of any other single app. 8*ae5b1ec8SZiwei Zhang 9*ae5b1ec8SZiwei Zhang## Overview 10*ae5b1ec8SZiwei Zhang 11*ae5b1ec8SZiwei ZhangTo build a snippet that instruments another app, you have to create a new 12*ae5b1ec8SZiwei Zhang[product flavor](https://developer.android.com/studio/build/build-variants.html#product-flavors) 13*ae5b1ec8SZiwei Zhangof your existing app with the snippet code built in. 14*ae5b1ec8SZiwei Zhang 15*ae5b1ec8SZiwei ZhangThe snippet code cannot run from a regular test apk because it requires a custom 16*ae5b1ec8SZiwei Zhang`testInstrumentationRunner`. 17*ae5b1ec8SZiwei Zhang 18*ae5b1ec8SZiwei Zhang## Tutorial 19*ae5b1ec8SZiwei Zhang 20*ae5b1ec8SZiwei Zhang1. In the `build.gradle` file of your existing app, create a new product flavor called `snippet`. 21*ae5b1ec8SZiwei Zhang 22*ae5b1ec8SZiwei Zhang ``` 23*ae5b1ec8SZiwei Zhang android { 24*ae5b1ec8SZiwei Zhang defaultConfig { ... } 25*ae5b1ec8SZiwei Zhang productFlavors { 26*ae5b1ec8SZiwei Zhang main {} 27*ae5b1ec8SZiwei Zhang snippet {} 28*ae5b1ec8SZiwei Zhang } 29*ae5b1ec8SZiwei Zhang } 30*ae5b1ec8SZiwei Zhang ``` 31*ae5b1ec8SZiwei Zhang 32*ae5b1ec8SZiwei Zhang1. Link against Mobly Snippet Lib in your `build.gradle` file 33*ae5b1ec8SZiwei Zhang 34*ae5b1ec8SZiwei Zhang ``` 35*ae5b1ec8SZiwei Zhang dependencies { 36*ae5b1ec8SZiwei Zhang snippetCompile 'com.google.android.mobly:mobly-snippet-lib:1.4.0' 37*ae5b1ec8SZiwei Zhang } 38*ae5b1ec8SZiwei Zhang ``` 39*ae5b1ec8SZiwei Zhang 40*ae5b1ec8SZiwei Zhang1. Create a new source tree called `src/snippet` where you will place the 41*ae5b1ec8SZiwei Zhang snippet code. 42*ae5b1ec8SZiwei Zhang 43*ae5b1ec8SZiwei Zhang1. In Android Studio, use the `Build Variants` tab in the left hand pane to 44*ae5b1ec8SZiwei Zhang switch to the snippetDebug build variant. This will let you edit code in the 45*ae5b1ec8SZiwei Zhang new tree. 46*ae5b1ec8SZiwei Zhang 47*ae5b1ec8SZiwei Zhang1. Write your snippet code in a new class under `src/snippet/java` 48*ae5b1ec8SZiwei Zhang 49*ae5b1ec8SZiwei Zhang ```java 50*ae5b1ec8SZiwei Zhang package com.my.app; 51*ae5b1ec8SZiwei Zhang ... 52*ae5b1ec8SZiwei Zhang public class EspressoSnippet implements Snippet { 53*ae5b1ec8SZiwei Zhang @Rpc(description="Pushes the main app button.") 54*ae5b1ec8SZiwei Zhang public void pushMainButton() { 55*ae5b1ec8SZiwei Zhang onView(withId(R.id.main_button)).perform(click()); 56*ae5b1ec8SZiwei Zhang } 57*ae5b1ec8SZiwei Zhang 58*ae5b1ec8SZiwei Zhang @Override 59*ae5b1ec8SZiwei Zhang public void shutdown() {} 60*ae5b1ec8SZiwei Zhang } 61*ae5b1ec8SZiwei Zhang ``` 62*ae5b1ec8SZiwei Zhang 63*ae5b1ec8SZiwei Zhang1. Create `src/snippet/AndroidManifest.xml` containing an `<instrument>` block 64*ae5b1ec8SZiwei Zhang and any classes that implement the `Snippet` interface in `meta-data` 65*ae5b1ec8SZiwei Zhang 66*ae5b1ec8SZiwei Zhang ```xml 67*ae5b1ec8SZiwei Zhang <?xml version="1.0" encoding="utf-8"?> 68*ae5b1ec8SZiwei Zhang <manifest xmlns:android="http://schemas.android.com/apk/res/android"> 69*ae5b1ec8SZiwei Zhang <application> 70*ae5b1ec8SZiwei Zhang <meta-data 71*ae5b1ec8SZiwei Zhang android:name="mobly-snippets" 72*ae5b1ec8SZiwei Zhang android:value="com.my.app.EspressoSnippet" /> 73*ae5b1ec8SZiwei Zhang </application> 74*ae5b1ec8SZiwei Zhang 75*ae5b1ec8SZiwei Zhang <instrumentation 76*ae5b1ec8SZiwei Zhang android:name="com.google.android.mobly.snippet.SnippetRunner" 77*ae5b1ec8SZiwei Zhang android:targetPackage="com.my.app" /> 78*ae5b1ec8SZiwei Zhang </manifest> 79*ae5b1ec8SZiwei Zhang ``` 80*ae5b1ec8SZiwei Zhang 81*ae5b1ec8SZiwei Zhang1. Build your apk by invoking the new `assembleSnippetDebug` target. 82*ae5b1ec8SZiwei Zhang 83*ae5b1ec8SZiwei Zhang1. Install the apk on your phone. You do not need to install the main app's 84*ae5b1ec8SZiwei Zhang apk; the snippet-enabled apk is a complete replacement for your app. 85*ae5b1ec8SZiwei Zhang 86*ae5b1ec8SZiwei Zhang1. In your Mobly python test, connect to your snippet .apk in `setup_class` 87*ae5b1ec8SZiwei Zhang 88*ae5b1ec8SZiwei Zhang ```python 89*ae5b1ec8SZiwei Zhang class HelloWorldTest(base_test.BaseTestClass): 90*ae5b1ec8SZiwei Zhang def setup_class(self): 91*ae5b1ec8SZiwei Zhang self.ads = self.register_controller(android_device) 92*ae5b1ec8SZiwei Zhang self.dut1 = self.ads[0] 93*ae5b1ec8SZiwei Zhang self.dut1.load_snippet(name='snippet', package='com.my.app') 94*ae5b1ec8SZiwei Zhang ``` 95*ae5b1ec8SZiwei Zhang 96*ae5b1ec8SZiwei Zhang6. Invoke your needed functionality within your test 97*ae5b1ec8SZiwei Zhang 98*ae5b1ec8SZiwei Zhang ```python 99*ae5b1ec8SZiwei Zhang def test_click_button(self): 100*ae5b1ec8SZiwei Zhang self.dut1.snippet.pushMainButton() 101*ae5b1ec8SZiwei Zhang ``` 102*ae5b1ec8SZiwei Zhang 103*ae5b1ec8SZiwei Zhang## Running the example code 104*ae5b1ec8SZiwei Zhang 105*ae5b1ec8SZiwei ZhangThis folder contains a fully working example of a snippet apk that uses espresso 106*ae5b1ec8SZiwei Zhangto automate a simple app. 107*ae5b1ec8SZiwei Zhang 108*ae5b1ec8SZiwei Zhang1. Compile the example 109*ae5b1ec8SZiwei Zhang 110*ae5b1ec8SZiwei Zhang ./gradlew examples:ex2_espresso:assembleSnippetDebug 111*ae5b1ec8SZiwei Zhang 112*ae5b1ec8SZiwei Zhang1. Install the apk on your phone 113*ae5b1ec8SZiwei Zhang 114*ae5b1ec8SZiwei Zhang adb install -r ./examples/ex2_espresso/build/outputs/apk/snippet/debug/ex2_espresso-snippet-debug.apk 115*ae5b1ec8SZiwei Zhang 116*ae5b1ec8SZiwei Zhang1. Use `snippet_shell` from mobly to trigger `pushMainButton()`: 117*ae5b1ec8SZiwei Zhang 118*ae5b1ec8SZiwei Zhang snippet_shell.py com.google.android.mobly.snippet.example2 119*ae5b1ec8SZiwei Zhang 120*ae5b1ec8SZiwei Zhang >>> print(s.help()) 121*ae5b1ec8SZiwei Zhang Known methods: 122*ae5b1ec8SZiwei Zhang pushMainButton(boolean) returns void // Pushes the main app button, and checks the label if this is the first time. 123*ae5b1ec8SZiwei Zhang startMainActivity() returns void // Opens the main activity of the app 124*ae5b1ec8SZiwei Zhang 125*ae5b1ec8SZiwei Zhang >>> s.startMainActivity() 126*ae5b1ec8SZiwei Zhang >>> s.pushMainButton(True) 127*ae5b1ec8SZiwei Zhang 128*ae5b1ec8SZiwei Zhang1. Press ctrl+d to exit the shell and terminate the app. 129