@blog.justoneplanet.info

日々勉強

Mozc for Androidのテストを読んでみる

EasyMockを使っている部分があるのでそこに関する自分用のメモ

public class MozcViewTest extends InstrumentationTestCaseWithMock

以下のようにしてモックを作る。

@SmallTest
public void testStartAnimation() {
    MozcView mozcView = createViewMockBuilder(MozcView.class)
        .addMockedMethods("getCandidateView", "getSymbolInputView", "expandDropShadowAndBackground", "collapseDropShadowAndBackground")
        .createMock();
    CandidateView candidateView = createViewMockBuilder(CandidateView.class)
        .addMockedMethods("getVisibility")
        .addMockedMethod("setVisibility", int.class)
        .createMock();
    SymbolInputView symbolInputView = createViewMockBuilder(SymbolInputView.class)
        .addMockedMethods("getVisibility")
        .addMockedMethod("setVisibility", int.class)
        .createMock();

以下のようにテストする。

    // Test startCandidateViewOut.
    {
      resetAll();// 今までのexpectで登録されたものをリセット
      expect(mozcView.getCandidateView()).andReturn(candidateView);// mozcViewのgetCandidateViewが1回呼ばれ返り値がcandidateViewであるかどうか
      candidateView.setVisibility(View.GONE);
      expect(mozcView.getSymbolInputView()).andReturn(symbolInputView);// mozcViewのgetSymbolInputViewが1回呼ばれ返り値がsymbolInputViewであるかどうか
      expect(symbolInputView.getVisibility()).andReturn(View.VISIBLE);// mozcViewのgetVisibilityが1回呼ばれ返り値がView.VISIBLEであるかどうか

      replayAll();
      mozcView.startCandidateViewOut();// このメソッドを呼んだ時のテスト

      verifyAll();// 検証実行
    }

startCandidateViewOutは以下のようになっているとする。

  void startCandidateViewOut() {
    getCandidateView().setVisibility(View.GONE);
    if (getSymbolInputView().getVisibility() != VISIBLE && isDropShadowExpanded) {
      collapseDropShadowAndBackground();
    }
  }

この時、startCandidateViewOutでモックに対してメソッドが必要以上に呼ばれるなどexpectと違った結果になるとテストが失敗する。

AndroidでIsolatedContextを使ってみる

■コード

以下のようにしてIsolatedContextのサブクラスを定義する。

public class HogeActivityTest extends ActivityInstrumentationTestCase2<Kaomoji> {
    private Kaomoji mActivity;
    private static final MockContentResolver RESOLVER = new MockContentResolver();
    private static class TestIsolatedContext extends IsolatedContext {
        private Context mContext;
        public TestIsolatedContext(ContentResolver resolver, Context targetContext) {
            super(resolver, targetContext);
            mContext = targetContext;
        }
        @Override
        public SharedPreferences getSharedPreferences(String name, int mode) {
            return mContext.getSharedPreferences("prefix_" + name, mode);
        }
    }
}

必要なメソッドはOverrideして実装する。以下のようにしてインスタンス化して、production環境に影響しない事を確かめる。

TestIsolatedContext context = new TestIsolatedContext(RESOLVER, mActivity);
SharedPreferences preferences = context.getSharedPreferences(Constants.KEY_USER_DATA, Context.MODE_PRIVATE);
String str = preferences.getString(Constants.KEY_USER_STRING, null);
assertEquals(str, null);// production側で文字列が保存されているのに関係しない

参考

ちょうどIsolatedContextを使ってるテストがなかったので何となく間に合わせ的なコードになってしまった。

AndroidでContentProviderをテストする

IsolatedContextの記事を書こうとしらProviderTestCase2の事を書いてなかった事に気づいたので書いておく。

■コード

public class ProviderTest extends ProviderTestCase2<Provider> {
    private Provider mProvider;
    private Uri mAuthority;

    public ProviderTest() {
        super(Provider.class, "");
    }
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mProvider = getProvider();
        mAuthority = Provider.URI;
    }
    
    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        mProvider = null;
        mAuthority = null;
    }
    
    public void testOnCreate() {
        assertFalse(mProvider.onCreate());
    }
    
    public void testGetType() {
        assertEquals(mProvider.getType(Provider.URI), null);
    }
    
    public void test1Insert() {
        String key   = "key1";
        String value = "value1";
        ContentValues values = new ContentValues();
        values.put("key", key);
        values.put("value", value);
        Uri result = mProvider.insert(mAuthority, values);
        assertEquals(mAuthority, result);
        
        Cursor cursor = mProvider.query(
                mAuthority,
                new String[]{"_id", "key", "value"},
                "`key` = ?",
                new String[]{key},
                null
        );
        assertTrue(cursor.moveToFirst());
        assertTrue(0 < cursor.getCount());
        assertEquals(cursor.getString(cursor.getColumnIndex("key")), key);
        assertEquals(cursor.getString(cursor.getColumnIndex("value")), value);
        cursor.close();
    }
    
    public void test2Update() {
        String key      = "key1";
        String value    = "valuevalue";
        ContentValues values = new ContentValues();
        values.put("key", key);
        values.put("value", value);
        int row = mProvider.update(
                mAuthority,
                values,
                "`key` = ?",
                new String[]{key}
        );
        assertTrue(0 < row);
        
        Cursor cursor = mProvider.query(
                mAuthority,
                new String[]{"_id", "key", "value"},
                "`key` = ?",
                new String[]{key},
                null
        );
        assertTrue(cursor.moveToFirst());
        assertTrue(0 < cursor.getCount());
        assertEquals(cursor.getString(cursor.getColumnIndex("key")), key);
        assertEquals(cursor.getString(cursor.getColumnIndex("value")), value);
        cursor.close();
    }
    
    public void test3Delete() {
        String key = "key1";
        int row = mProvider.delete(mAuthority, "`key` = ?", new String[]{key});
        assertTrue(row > 0);
    }
}

ProviderTestCase2のコンストラクタがIsolatedContextオブジェクトを生成し、production環境とは別の環境で実行される。メソッドの実行順序を指定しているのが良くない。

android-support-v4.jarを使ったプロジェクトのテストをする

テスト対象のプロジェクトにおいて以下の操作をする。

propaties > Java Build Path > Order and Export > android-support-v4.jarにチェックを入れる。

.classpath

以下のようにexported属性が付加されている。

<classpathentry exported="true" kind="lib" path="libs/android-support-v4.jar"/>

悪い例

テストプロジェクトにandroid-support-v4.jarをインポートすると以下のようなエラーがでる。

java.lang.RuntimeException: Exception during suite construction
at android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests.testSuiteConstructionFailed(TestSuiteBuilder.java:239)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1448)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
at android.test.suitebuilder.TestMethod.instantiateTest(TestMethod.java:87)
at android.test.suitebuilder.TestMethod.createTest(TestMethod.java:73)
at android.test.suitebuilder.TestSuiteBuilder.addTest(TestSuiteBuilder.java:263)
at android.test.suitebuilder.TestSuiteBuilder.build(TestSuiteBuilder.java:185)
at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:373)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3285)
at android.app.ActivityThread.access$2200(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:987)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3728)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
at dalvik.system.NativeStart.main(Native Method)

参考

AndroidTestCaseでテストアプリ側のContextを取得する

メモ。

public class AndroidExtendedTestCase extends AndroidTestCase {
    public Context getTextContext() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        Class<? extends AndroidExtendedTestCase> clz = (Class<? extends AndroidExtendedTestCase>) this.getClass();
        Method method = clz.getMethod("getTestContext");
        Context context = (Context) method.invoke(this);
        return context;
    }
}

参考

robotiumを使ってみる

@ayunyanさんに教えていただいたので使ってみる。

■シナリオ

以下のようにandroid版顔文字辞典を操作するとする。

  1. メニューを開く
  2. カテゴリ追加をタップする
  3. カテゴリ名を入力し登録する(a)
  4. 登録したカテゴリ(a)をロングタップする
  5. 編集を選択する
  6. カテゴリ名を変更して登録する(b)
  7. 編集したカテゴリ(b)をロングタップする
  8. 削除をタップする

■テストコード

以下のようにして「みんなの顔文字辞典」のカテゴリー追加・編集・削除のダイアログのテストを行う。

package info.justoneplanet.android.kaomoji.test.dialog;

import com.jayway.android.robotium.solo.Solo;

import info.justoneplanet.android.kaomoji.KaomojiFavorite;
import info.justoneplanet.android.kaomoji.R;
//import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;

/**
 * カテゴリを追加するダイアログのテストケース
 * @author justoneplanet
 * カテゴリの登録・編集・削除は決まった順番で行われる必要があるためメソッド名で順序を指定した
 */
public class CategoryDialogBuilderTest extends ActivityInstrumentationTestCase2<KaomojiFavorite> {

    private KaomojiFavorite mActivity;
    //private Instrumentation mInstrumentation;
    private Solo solo;
    
    private static final String OLD_CATEGORY_NAME = "新しいカテゴリ";
    private static final String NEW_CATEGORY_NAME = "新カテゴリ";

    public CategoryDialogBuilderTest() {
        super("info.justoneplanet.android.kaomojifavorite", KaomojiFavorite.class);
    }
    
    @Override
    public void setUp() throws Exception {
        super.setUp();
        mActivity = getActivity();
        //mInstrumentation = getInstrumentation();
        solo = new Solo(getInstrumentation(), getActivity());
    }
    
    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        mActivity = null;
        //mInstrumentation = null;
    }
    
    /**
     * カテゴリを正しく追加できるか
     * カテゴリaを登録する
     */
    public void testCategory1Add() {
        solo.clickOnMenuItem(mActivity.getString(R.string.menu_category_add));// メニュー>カテゴリを追加
        solo.enterText(0, OLD_CATEGORY_NAME);// 新しいカテゴリ名を入力
        solo.clickOnButton(mActivity.getString(R.string.register));// 登録ボタン
    }
    
    /**
     * カテゴリを正しく編集できるか
     * カテゴリaを編集してカテゴリbに名前を変える
     */
    public void testCategory2Edit() {
        solo.clickLongOnText(OLD_CATEGORY_NAME);// テキストで探索してリストの要素をロングタップ
        solo.clickOnText(mActivity.getString(R.string.edit));// ダイアログ内カテゴリの編集をタップ
        solo.clearEditText(0);// テキストを消す
        solo.enterText(0, NEW_CATEGORY_NAME);// 新カテゴリ名を入力
        solo.clickOnButton(mActivity.getString(R.string.register));// 登録ボタン
    }
    
    /**
     * カテゴリを削除できるか
     * カテゴリbを削除する
     */
    public void testCategory3Delete() {
        solo.clickLongOnText(NEW_CATEGORY_NAME);// テキストで探索してリストの要素をロングタップ
        solo.clickOnText(mActivity.getString(R.string.delete));// カテゴリの削除をクリック
        solo.waitForDialogToClose(1000);// すぐに終了してしまうと削除クエリが実行されなかったので
    }
}

操作する要素をテキストで指定できる探索が便利!

clickInListについて

以下のようにして使用した。おそらく表示しているlistアイテムの配列の中でのpositionを指定していると思われる。また、表示されていないlistアイテムを上からの位置で指定することはできなかった。

private String tapEmoticonAfterCategory(String category, int position) {
    solo.clickOnText(category);
    solo.waitForDialogToClose(1000);// 作用するまでwait
    ArrayList<TextView> list = solo.clickInList(position);// 表示されているlistの要素配列のposition
    solo.waitForDialogToClose(1000);// 作用するまでwait
    Log.e("tapped", String.valueOf(list.get(0).getText()));
    return String.valueOf(list.get(0).getText());
}

■参考

おまけ

当初は以下のようにThread.sleepを使用していたが、ProgressDialogを表示し通信結果を待つような場合に期待した動作にならなかった。

    /**
     * カテゴリを削除できるかテストする
     * @throws InterruptedException 
     */
    public void testCategory3Delete() throws InterruptedException {
        solo.clickLongOnText(NEW_CATEGORY_NAME);// テキストで探索してリストの要素をロングタップ
        solo.clickOnText(mActivity.getString(R.string.delete));// カテゴリの削除をクリック
        Thread.sleep(1000);// 期待の動作とならない
    }

テキスト(半角カナ?)によってはいまいち探索できないときがある。

AsyncTaskのテストをする

■コード

以下のようにUIスレッドでAsyncTaskをインスタンス化する必要がある。

public class EveryoneTaskTest extends ActivityInstrumentationTestCase2<Kaomoji> {
    private Kaomoji mActivity;
    private Instrumentation mInstrumentation;
    private EveryoneTask everyoneHttp;
    private CountDownLatch countDownLatch;
    private String mResult;
    
    public EveryoneTaskTest() {
        super("info.justoneplanet.android.kaomoji", Kaomoji.class);
    }
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mActivity = getActivity();
        mInstrumentation = getInstrumentation();
        countDownLatch = new CountDownLatch(1);
    }
    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        mActivity = null;
        mInstrumentation = null;
    }
    
    public void testExecute() throws InterruptedException, JSONException {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                everyoneHttp = new EveryoneTask(new EveryoneTask.Observer(){
                    @Override
                    public void onHttpUpdate(String result, MODE mode) {
                        mResult = result;
                        countDownLatch.countDown();// カウントを0にする
                    }
                });
                everyoneHttp.execute(null);
            }
        });
        countDownLatch.await();// countが0になるまで処理を待機
        
        // 要素の検証
        JSONObject elm;
        JSONArray ary = new JSONArray(mResult);
        assertTrue(ary.length() == 150);
    }
}

失敗例

以下のようにアプリのメインスレッド以外でAsyncTaskのインスタンス化を行なってはならない。挙動が不安定になりonPostExecuteが実行されない。

/**
 * みんなな顔文字を通信して取得するクラスのテストケース
 * @author justoneplanet
 */
public class EveryoneHttpTest extends AndroidTestCase implements EveryoneHttp.Observer {
    CountDownLatch countDownLatch;
    private EveryoneHttp everyoneHttp;
    private String mResult;
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        countDownLatch = new CountDownLatch(1);
    }

    public void testDoInBackground() throws InterruptedException, JSONException {
        everyoneHttp = new EveryoneHttp(this);// get everyone's emoticons from transfer
        everyoneHttp.execute();
        countDownLatch.await();// countが0になるまで処理を待機
        
        JSONArray ary = new JSONArray(mResult);
        assertTrue(ary.length() == 150);// 要素数の検証
        
        // 要素の検証
        JSONObject elm = ary.getJSONObject(0);
        Log.e("elm", elm.toString());
        assertFalse(elm.getString("face").equals(null));
        assertFalse(elm.getString("tag").equals(null));
    }
    
    /**
     * 通信完了後に実行される
     */
    @Override
    public void onHttpUpdate(String result) {
        mResult = result;
        countDownLatch.countDown();// カウントを0にする
    }
}

非同期処理自体はAsyncTaskをwrapしたクラスで行なっている。Observerを使ったのでテストコードもすっきり。

androidでAndroidWebDriverを使ってみる

元ネタはTim BrayのIntroducing Android WebDriverという記事。

■準備

テストプロジェクトで右クリックし「propaties> Java Build Path > Libraries > Add External JARs」で以下のjarをインポートする。

  • android_webdriver_library-srcs.jar
  • android_webdriver_library.jar
  • guava-10.0.1.jar

■コード

Tim様の記事ではgoogle.comが使用されているが以下のような理由によってテストにパスしない。

  • ロケールが違うので日本語表示される
  • 結果がリッチすぎて上手くdomを抽出できない

テストコード内でgoogle.comのリンクをクリックするようにできると思うが、html構造を把握するのが大変なので以下のようなコードでmozillaのサイトでテストすることにした。

package bootcamp2011.android.test;

import java.util.List;

import bootcamp2011.android.Bootcamp2011Activity;
import android.test.ActivityInstrumentationTestCase2;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.android.AndroidWebDriver;;

public class Bootcamp2011ActivityTest extends
        ActivityInstrumentationTestCase2<Bootcamp2011Activity> {

    private AndroidWebDriver driver;

    public Bootcamp2011ActivityTest() {
        super("bootcamp2011.android.bootcamp2011activity", Bootcamp2011Activity.class);
    }
    
    @Override
    protected void setUp() throws Exception {
      driver = new AndroidWebDriver(getActivity());
    }
    
    @Override
    protected void tearDown() {
       driver.quit();
    }
    
    public void testGoogleShouldWork() {
        // mozillaのサイトを訪問
        driver.get("https://developer.mozilla.org/ja/JavaScript");

        // 検索boxを抽出して文字入力し送信
        WebElement searchBox = driver.findElement(By.id("q"));
        searchBox.sendKeys("querySelector");
        searchBox.submit();

        // 検索結果にquerySelectorという文字列が含まれているかテスト(仮)
        WebElement resultSection = driver.findElement(By.id("search-results"));
        List<WebElement> searchResults = resultSection.findElements(By.tagName("table"));
        WebElement result = searchResults.get(0);
        assertTrue(result.getText().contains("querySelector"));
    }
}

By.cssSelector()というメソッドがあるのだが上手く働かない…一応、動作するサンプルが「android-sdk-mac_x86/extras/google/webdriver/TestAnAndroidWebApp/src/simple/app/test/SimpleGoogleTest.java」にある。

androidでTouchUtilsを使ってテストをする

以下のようにしてTouchUtilsを使用することができる。

public void testPushListByTouchUtils()
{
    LinearLayout item = (LinearLayout) mActivity.getListView().getChildAt(0);
    //TouchUtils.tapView(this, item);// 画面に触れている状態
    TouchUtils.clickView(this, item);// 画面から指が離れた状態
    String face = (String) ((TextView) item.findViewById(R.id.list_face)).getText();
    ClipboardManager cm = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
    assertEquals(face, cm.getText());
}

SecurityExceptionなどが発生すると書いてある文献も見られるが自分の環境では発生しなかった。但し、Viewの選択が間違っていてnullであったりすると発生する(なぜNullPointer〜でないのか…)。ちなみに同様のテストケースをTouchUtilsを使用せずに書くと以下のようになる。

public void testPushList()
{
    mActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            LinearLayout item = (LinearLayout) mActivity.getListView().getChildAt(0);
            mActivity.getListView().performItemClick(item, position, 0));
            String face = (String) ((TextView) item.findViewById(R.id.list_face)).getText();
            ClipboardManager cm = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
            MainActivityTest.assertEquals(face, cm.getText());
        }
    });
    mInstrumentation.waitForIdleSync();
}

TouchUtilsは別アプリがタップするようなイメージで、Viewに対して発生させるイメージだ。従って、performItemClickはUIThreadで実行する必要がある。

androidでJUnitを使ってテストする

秋葉原Androidアプリ開発勉強会に行ってきたヽ(•̀ω•́ )ゝ✧自分の題材はユニットテスト。

iOSアプリケーションではテストをするためにターゲットを追加する。androidではテストするためにプロジェクトを作る。

■テストプロジェクト

Package Explorerで右クリック「New > Others > Android Test Project」を選択し、Test Targetに既存のアプリを指定して「Finish」をクリックする。

■テストクラス

パッケージで右クリック、「New > Class」を選択して以下のように入力する。

Name MainActivityTest
Superclass android.test.ActivityInstrumentationTestCase2<MainActivity>

MainActivityをimportし、コンストラクタの引数を除去して以下のようにする。

public MainActivityTest() {
    super("info.justoneplanet.android.mainactivity", MainActivity.class);
    setActivityInitialTouchMode(false);
}

■テストコード

以下のようにとりあえず書いてみた。

package info.justoneplanet.android.sample.test;

import info.justoneplanet.android.sample.MainActivity;
import android.app.Instrumentation;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase2;
import android.text.ClipboardManager;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.TextView;
import info.justoneplanet.android.sample.R;

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity>
{
    private MainActivity mActivity;
    private Instrumentation mInstrumentation;

    public MainActivityTest() {
        super("info.justoneplanet.android.mainactivity", MainActivity.class);
        setActivityInitialTouchMode(false);
    }
    
    @Override
    protected void setUp() throws Exception
    {
        super.setUp();
        mActivity = getActivity();
        mInstrumentation = getInstrumentation();
    }
    
    @Override
    protected void tearDown() throws Exception
    {
        super.tearDown();
        mActivity = null;
        mInstrumentation = null;
    }
    
    /**
     * testPushList
     * まあサンプル
     */
    public void testPushList()
    {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // テスト対象アプリのUIを制御するコードはこっちに書くよ
                MainActivityTest.assertEquals(true, true);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(true, true);
    }
}

ちなみに「みんなの顔文字辞典」のテストケース(一部)は以下のようになっている。

/**
 * testPushList
 * タップした部分の顔文字とクリップボードの顔文字が同じかテストする
 */
public void testPushList()
{
    mActivity.runOnUiThread(new Runnable() {
        private int position = 0;
        private LinearLayout item;
        
        /**
         * getClipBoardText
         * クリップボードのテキストを取得して返す
         * @return
         */
        private String getClipBoardText() {
            ClipboardManager cm = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
            Log.e("face", (String) cm.getText());
            return (String) cm.getText();
        }
        
        /**
         * getFaceInListItem
         * ListViewのitemの中に含まれる文字列を返す
         * @param item
         * @return
         */
        private String getFaceInListItem(LinearLayout item) {
            String face = (String) ((TextView) item.findViewById(R.id.list_face)).getText();
            Log.e("face", face);
            return face;
        }
        
        /**
         * getListItemByTappedPosition
         * indexを指定してListViewの中のitemを返す
         * @param position
         * @return LinearLayout item
         */
        private LinearLayout getListItemByTappedPosition(int position) {
            LinearLayout item = (LinearLayout) mActivity.getListView().getChildAt(position);
            Log.e("result", String.valueOf(mActivity.getListView().performItemClick(item, position, 0)));// tap!
            return item;
        }
        
        @Override
        public void run() {
            position = 0;
            item = getListItemByTappedPosition(position);
            KaomojiEveryoneTest.assertEquals(getFaceInListItem(item), getClipBoardText());
            
            position = 5;
            item = getListItemByTappedPosition(position);
            KaomojiEveryoneTest.assertEquals(getFaceInListItem(item), getClipBoardText());
            
            position = 10;
            item = getListItemByTappedPosition(position);
            KaomojiEveryoneTest.assertEquals(getFaceInListItem(item), getClipBoardText());
        }
    });
    mInstrumentation.waitForIdleSync();
}