1. ホーム
  2. アンドロイド

Androidユニットテスト完全解説

2022-02-28 10:07:47
<パス

  自動テストは面倒くさい?正直言って、そうです。学習コストがかかります。しかし、自動化されたテストには以下のような利点があります。

  • 時間の節約:テストするアクティビティを1つ1つ順番に指定する必要がない
  • ユニットテスト。Javaでユニットテストができるのに、なぜAndroidではできないのか?
  • ワンクリック適応:説明なし

主なAndroid自動テストフレームワークは Espresso、UI Automator、Robolectricです。

1. Javaユニットテスト

Android Studio(以下、as)は、皆さんもご存知の通り、純粋なJavaのコードを実行することができます。ここでは、ウォーミングアップとして、asがどのようにJavaのコードを実行するのかを簡単に説明します
まず、以下のようにapp->src->testディレクトリの下に、AndroidTestパッケージは、Androidの仕事のためのテストです、最初に彼を無視し、テストパッケージを開きます。

<センター

<センター

ここでは、asが直接開けるようにテストクラスを作成しています。Junit4のテストパッケージを使用したasの主なコードは以下の通りです。

@RunWith(JUnit4.class)
public class ExampleUnitTest {
    @Before
    public void before(){
        // work before the test
    }
    @After
    public void after()
    {
       // Work after the test is done
    }
    @Test
    public void addition_isCorrect() {
        // Main work
    }
}


これが最も単純なJavaのテストです。では、ウォーミングアップをして、この記事の本題に入りましょう。

2、Androidユニットテスト - Espresso

  AndroidJUnitRunner クラスは JUnit テストランナーであり、Espresso および UI Automator テストフレームワークを使用するテストクラスを含む JUnit 3 または JUnit 4 スタイルのテストクラスを Android デバイスで実行することが可能です。
  このテストランナーは、JUnit 3 および JUnit 4(JUnit 4.10 まで)のテストと互換性があります。ただし、JUnit 3 と JUnit 4 のテストコードを同じパッケージで混在させると、予期しない結果になる可能性があるので、避ける必要があります。デバイスやエミュレータ上で実行する JUnit 4 のテストクラスを作成する場合は、テストクラスの前に @RunWith (AndroidJUnit4.class) アノテーションを付けなければなりません。

まず、appの下のbuild.gradleの依存関係を見ます。

dependencies {
     androidTestCompile 'com.android.support:support-annotations:25.4.0'
    androidTestCompile 'com.android.support.test:runner:1.0.0' 
    androidTestCompile 'com.android.support.test:rules:1.0.0' 
    androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.2'
}
android {
    defaultConfig {
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
}


依存関係の衝突がある場合は、以下のコードを追加してください。

androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})


2.1 アプリケーションの取得

Webテストの最も一般的なユースケースは、プロジェクトが大規模でコンパイルに時間がかかる場合、リクエストの結果を見るだけでもかなりの時間がかかり、耐えられないので、以下のコードのようにAndroidのユニットテストでリクエストをシミュレートすることができます。

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Before
    public void init() {
        Context appContext = InstrumentationRegistry.getTargetContext();
        x.Ext.init((Application) appContext.getApplicationContext());
    }

    @Test
    public void useAppContext() {
        // Context of the app under test.
        RequestParams requestParams = new RequestParams("https://www.baidu.com/");
        String str = x.http().getSync(requestParams, String.class);
        System.out.println("\n"+str+"\n");
    }
}


InstrumentationRegistry を使って、コンテキストオブジェクトを取得し、コンテキストを使ってアプリケーションオブジェクトを取得します。 ご注意ください をテストメソッド内で使用する必要があります。 同期 そうでなければ、テストケースは単にコールバックメソッドを無視してプログラムを直接終了してしまい、結果的にリクエストの結果を利用できなくなります。

Androidのユニットテストは、小テスト、中テスト、大テストに分類され、以下のように区別されます。

  • SmallTest:システムから分離して実行され、実行時間は最大200msと短い
  • MediumTest:複数のコンポーネントを統合し、エミュレータ上でも実機上でも実行可能、実行時間は最大1000ms
  • LargeTest: UIフローのテストジョブを実行し、エミュレータまたは実機でアプリが期待通りに動作することを確認できます。最大実行時間は1000ms

アサーションは、Androidのユニットテストにおいて、変数の値が期待値を満たしているかどうかを判断するために使用することができ、一般的に使用されるのはassertThat, assertEquals, assertNotSameなどです。

2.2 対応するコンポーネントの取得

フレームワークでは、テスト対象のアクティビティを管理するためにActivityTestRuleを提供しています。例えば、MainActivityに対応するレイアウトファイルは次のようになります。

<?xml version="1.0" encoding="utf-8"? >
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:id="@+id/main_text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>



MainActivityのコードをここに掲載する代わりに、テストコードを見てみましょう。

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainTest {
    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
            MainActivity.class);

    @Test
    public void Run() {
        onView(withId(R.id.main_text)).perform(
                typeText("Hello MainActivity!"), closeSoftKeyboard());
    }
}


ここでひとこと。

  • withId(R.id.main_text): IDによって対応するコンポーネントを見つけ、それをMatcherにラップします。
  • onView():コンポーネントにウィンドウフォーカスを与え、ViewInteractionのインスタンスを返す。
  • perform():コンポーネントが実行する必要のあるタスクで、ViewActionのインスタンスを渡します。
  • typeText():入力文字列のタスク、似たようなことをするreplaceTextメソッドもありますが、入力アニメーションはありません。
  • closeSoftKeyboard():ソフトキーボードを閉じます。

上記は最も基本的な自動化テストコードです。以下のように、Runメソッドの横にあるRunボタンをクリックするだけで、デバイス上で直接実行することができます。

<センター <センター

クリックイベントも同様です。

onView(withId(R.id.main_text)).perform(click());


ダブルクリックイベント。

onView(withId(R.id.main_text)).perform(doubleClick());


期待に応えているかどうかを判断する

onView(withId(R.id.main_text)).check(matches(withText("Hello MainActivity!")));           


もっと見る アクションを見る クラスはAPIを提供します。

2.3 listViewのクリックイベントをシミュレートする

上記はユニークなIDのイベントの場合ですが、同じIDのコンポーネントが複数ある場合はどうでしょうか?例えば、listViewのitemのクリックイベントをシミュレートした場合、各itemをどのように区別するのでしょうか?まず、同じIDを持つコンポーネントが複数ある場合の処理方法を確認しましょう。
IDで対応するビューを見つけることができるのはご存じだと思いますが、ここでは表示されたテキストでもビューを見つけることができます。

onView(withText("Hello MainActivity!"));


では、IDや表示されたテキストからユニークビューを探し出すことはできないのでしょうか?次のようになります。

onView(allOf(withId(R.id.main_text), withText("Hello MainActivity!")));


または、次のように不一致のビューをフィルタリングします。

onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));


もっと見る ビューマッチャ が提供するAPI

次に、リストビュー(GridViewとSpinnerの両方)のクリックイベントをシミュレートする方法について説明します。

まず、SecondActivityを作成します。

public class ListActivity extends AppCompatActivity {
    private ListView listView ;
    private List<HashMap<String ,String>> data = new ArrayList<>();
    public static final String KEY = "key";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        listView = findViewById(R.id.list_view);
        initDate();
        listView.setAdapter(new SimpleAdapter(this,data,
                R.layout.item_list,
                new String[]{KEY},
                new int[]{R.id.item_list_text}));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<? > parent, View view, int position, long id) {
                Toast.makeText(ListActivity.this,data.get(position).get(KEY),Toast.LENGTH_LONG).show();
            }
        });
    }

    private void initDate() {
        for(int i =0 ;i < 90 ;i++){
            HashMap<String,String> map = new HashMap<>();
            map.put(KEY,"first"+(1+i)+"column");
            data.add(map);
        }
    }
}


  対応するレイアウトファイルはlistViewで、アイテムに対応するレイアウトはtextViewなので、ここには掲載せず、テストクラスに絞って掲載します。

@RunWith(AndroidJUnit4.class)
@LargeTest
public class ListViewTest {
    private static final String TAG = "ListViewTest ";
    @Rule
    public ActivityTestRule<ListActivity> mActivityRule = new ActivityTestRule<>(
            ListActivity.class);

    @Before
    public void init() {
        mActivityRule.getActivity();
    }

    @Test
    public void Run() {
        onData(allOf(is(instanceOf(Map.class)),
                hasEntry(equalTo(ListActivity.KEY), is("10th column")))).perform(click()));
    }
}



  ここで選択されたデータは 10行目 で、項目に対するクリックアクションを実行し、ここでは ハッシュエントリー () メソッドでは、2つのMatcher、つまり、マップのキー名と対応する値を渡す必要があります。マップのキーと値は、アイテムを一意に識別するために使用され、対応するアイテムは、以下のように、ビューと同様のアクションを実行するために使用することができます。

<センター <センター

  アニメーションは比較的速いですが、クリックイベントを実行する前にリストビューがまず10行目までスクロールしていることがわかります。これは、Espressoがターゲット要素をスクロールして、その要素にフォーカスを当てる役割を担っているためです。

  早速、recycleViewが主流でlistviewはほとんど使われていないよ~~、大丈夫、recycleViewのテストを自動化する方法を見てみよう、という指摘をした学生もいました。

2.4 recycleViewのクリックイベントをシミュレートする

recycleViewの自動テストには、以下の依存関係を追加する必要があります。 注意事項 は、これまでの依存関係の上に、次のコードを追加することです。

androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.0'
androidTestCompile 'com.android.support:recyclerview-v7:25.4.0'


以下の内容でRecyclerActivityを作成します。

public class RecyclerActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private RecyclerAdapter<String> adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler);
        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new RecyclerAdapter<>(this, R.layout.item_list);
        recyclerView.setAdapter(adapter);
        List<String> list = new ArrayList<>();
        for(int i =0 ;i < 50 ;i++){
            list.add("first"+(1+i)+"column");
        }
        adapter.setData(list);
    }
}


  対応するレイアウトファイルはcyclerviewで、項目のレイアウトはtextViewのみなので、ここには掲載しません。 adapterも以下のように、textViewにclickイベントを与えるだけの非常にシンプルなものです。

public class RecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {.
    private List<T> data = new ArrayList<>();
    private Context コンテキスト ;
    private int layout;

    public RecyclerAdapter(Context context, int layout) { { {RecyclerAdapter(context, int layout)
        this.context = context;
        this.layout = layout;
    レイアウト; }.

    public void setData(List<T> データ) {
        this.data.clear()を実行します。
        this.data.addAll(データ);
        notifyDataSetChanged();
    

    オーバーライド
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { {...
        return new Holder(LayoutInflater.from(context))
                .inflate(layout,null,false));
    


    オーバーライド
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { (パブリックボイドオンバインドビューホルダー)
        ホルダー holder1 = (Holder) holder;
        holder1.textView.setText(data.get(position).toString());
        holder1.itemView.setOnClickListener(new View.OnClickListener() {)
            オーバーライド
            
                Toast.makeText(context,data.get(position).toString(),Toast.LENGTH_LONG).show() を実行します。
            
        });
    }

    オーバーライド
    パブリック int getItemCount() {
        return data.size();
    
    private class Holder extends RecyclerView.ViewHolder{...
        TextView textView ;
        パブリックホルダー(View itemView) {
            super(itemView)。
            textView = itemView.findViewById(R.id.item_list_text);
        
    }
}



次に、テストクラスを見てみましょう。

@RunWith(AndroidJUnit4.class)
@LargeTest
public class RecycleViewTest {
    private static final String TAG = "ExampleInstrumentedTest";
    @Rule
    public ActivityTestRule<RecyclerActivity> mActivityRule = new ActivityTestRule<>(
            RecyclerActivity.class);

    @Test
    public void Run() {
        onView(ViewMatchers.withId(R.id.recycler_view))
                .perform(RecyclerViewActions.actionOnItemAtPosition(10, click()));

    }
}


  runメソッドでは、基本的に前のものと似ていることがわかりますが、違いはRecyclerViewActionsクラスによって提供されるAPIを通じてタスクを実行する必要があることです。 actionOnItemAtPositionの最初のパラメータはrecycleviewのアイテム位置で、2番目のパラメータは対応するアクションで、効果は アクションOnItemAtPositionの最初のパラメータはrecycleviewのアイテム位置で、2番目のパラメータは対応するアクションで、効果はアクションのものと同じになります。
  ここで、recycleview のテストクラスが listView よりも優れていることがわかります。listViewは対応するアイテムをその値によって見つけるのに対して、recycleviewはその位置によって直接見つけるのです。

2.5 アクションバーをユーザーがクリックしたときのシミュレート

次のメインコードで新しいMenuActivityを作成します。

public class MenuActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_test, menu);
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Toast.makeText(this,item.getTitle(),Toast.LENGTH_SHORT).show();
        return super.onOptionsItemSelected(item);
    }
}


メニューレイアウトのコードは以下の通りです。

<?xml version="1.0" encoding="utf-8"? >
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:android1="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/nav_1"
        android:title="item1"
        android1:showAsAction="never" />
    <item
        android:id="@+id/nav_2"
        android:title="item2"
        android1:showAsAction="never" />
</menu>



テストコードは以下の通りです。

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MenuTest {
    @Rule
    public ActivityTestRule<MenuActivity> mActivityRule = new ActivityTestRule<>(
            MenuActivity.class);
    @Test
    public void test(){
        //openmenu
        openContextualActionModeOverflowMenu();
        // simulate clicking item2
        onView(withText("item2"))
                .perform(click());
    }
}


その効果は次の通りです。

<センター <センター

テスト中にprepare例外を呼んでいないMainLooperに遭遇した場合

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Handler at android.os.
(Handler.java:200)
Handler.
(Handler.java:114)
at android.widget.Toast$TN.
(Toast.java:344)
at android.widget.Toast.
(Toast.java:100)


この問題は、次のコードを追加することで解決できます。

    @Test
    public void test() {
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                //test content
            }
        });
    }


3、Androidユニットテスト - Robolectric

  あなたのアプリのテスト環境で、ユニットテストがより広範囲にAndroidフレームワークと相互作用する必要がある場合、Robolectric.を使用してください。これは、ワークステーション上または継続的インテグレーション環境において、エミュレータなしで通常のJVMでテストを実行し、Androidデバイス上でテストを実行するのとほぼ同じ忠実度を持ちながら、デバイステストの実行よりも高速に実行できるようにします。Android プラットフォームの以下の点をサポートしています。

  • Android 4.1以降
  • Android Gradle プラグイン 2.4 以降
  • コンポーネントのライフサイクル
  • イベントループ
  • すべてのリソース SDK、リソース、ネイティブメソッド

グレードの設定。

testImplementation "org.robolectric:robolectric:3.8"
testImplementation "org.assertj:assertj-core:1.7.0"
// robolectric corresponding to the support-v4 package
testImplementation 'org.robolectric:shadows-support-v4:3.0'

android {
  testOptions {
    unitTests {
      includeAndroidResources = true
    }
  }
}


基本的な使い方は以下の通りです。

@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {

  @Test
  public void clickingButton_shouldChangeResultsViewText() throws Exception {
    MyActivity activity = Robolectric.setupActivity(MyActivity.class);

    Button button = (Button) activity.findViewById(R.id.button);
    TextView results = (TextView) activity.findViewById(R.id.results);

    button.performClick();
    assertThat(results.getText().toString()).isEqualTo("Robolectric Rocks!");
  }
}


ロボエレクトリックコミュニティ これはすでに詳しく説明されているので、ここでは割愛します

迷ったときは、記事の最後にあるデモを参考にするとよいでしょう。なお、Robolectric の関連するテストは test ディレクトリにあり、Android 環境をモック化することができます。

4、Androidのテスト - UI Automator

最初に依存関係を設定する

dependencies {
    androidTestCompile 'com.android.support:support-annotations:25.4.0'
    androidTestCompile 'com.android.support.test:runner:1.0.0' 
    androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
    androidTestCompile 'org.hamcrest:hamcrest-integration:1.3'

}


UI Automator は Android 4.3 (API level 18) を最低限サポートしています。

MainActivityのコンポーネントは、editText、textView、ボタンの4つで、レイアウトは掲載していませんが、MainActivityのJavaコードでは、主にclickメソッドで、以下のようになります。

  @Override
    public void onClick(View view) {
        // Get the text from the EditText view.
        final String text = mEditText.getText().toString();

        final int changeTextBtId = R.id.changeTextBt;
        final int activityChangeTextBtnId = R.id.activityChangeTextBtn;

        if (view.getId() == changeTextBtId) {
            // display the text content in edit to the textView
            mTextView.setText(text);
        } else if (view.getId() == activityChangeTextBtnId) {
            //start a new activity and pass the text to the new activity to display
            Intent intent = ShowTextActivity.newStartIntent(this, text);
            startActivity(intent);
        }
    }



主にテストコードを見てみると、ここでChangeTextBehaviorTestテストクラスが作成されています。

@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = 18)
public class ChangeTextBehaviorTest {

    private static final String BASIC_SAMPLE_PACKAGE
            = "com.example.android.testing.uiautomator.BasicSample";

    private static final int LAUNCH_TIMEOUT = 5000;

    private static final String STRING_TO_BE_TYPED = "UiAutomator";

    private UiDevice mDevice;

    @Before
    public void startMainActivityFromHomeScreen() {
        // Get an instance of UiDevice
        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

        // Simulate the user clicking the home button
        mDevice.pressHome();
        // Get the name of the package to be loaded
        final String launcherPackage = getLauncherPackageName();
        //judge if it is empty
        assertThat(launcherPackage, notNullValue());
        //wait for information about the target package
        mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);

        // Start the target activity, i.e. MainActivity
        Context context = InstrumentationRegistry.getContext();
        final Intent intent = context.getPackageManager()
                .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances
        context.startActivity(intent);

        // Wait for the app to appear
        mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
    }


    @Test
    public void testChangeText_sameActivity() {
        //fill the STRING_TO_BE_TYPED content into the edittext
        mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput"))
                .setText(STRING_TO_BE_TYPED);
        // simulate the user's click event for the component with ID changeTextBt
        mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "changeTextBt"))
                .click();

        // wait to get the content of the textView with ID textToBeChanged in MainActivity, waiting time is 500ms
        UiObject2 changedText = mDevice
                .wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "textToBeChanged")),
                        500 /* wait 500ms */);
        // determine if this is correct
        assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED)));
    }

    @Test
    public void testChangeText_newActivity() {
        // same as above
        mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput"))
                .setText(STRING_TO_BE_TYPED);
        mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "activityChangeTextBtn"))
                .click();

        // Verify the test is displayed in the Ui
        UiObject2 changedText = mDevice
                .wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "show_text_view"))),
                        500 /* wait 500ms */);
        assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED)));
    }

    /**
     * Get the package name
     */
    private String getLauncherPackageName() {
        // Create launcher Intent
        final Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);

        // Use PackageManager to get the launcher package name
        PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
        return resolveInfo.activityInfo.packageName;
    }
}


フレームワークのロジックは、アプリを使用するユーザーをシミュレートすることです。このテストケースの主な流れは、ユーザーがデスクトップ上のターゲットアプリをクリックして中に入り、文字列を入力し、ユーザーがactivityChangeTextBtnコンポーネントをクリックしてShowTextActivityにジャンプし、表示するコンテンツを渡します。その後、changeTextBtコンポーネントをクリックし、ユーザー入力を表示します。
その効果は次のとおりです。

<センター <センター

テストクラスには3つのメソッドがあり、そのうちテスト前にUiDeviceのインスタンスを取得する必要があるのは、以下の通りです。

  • getInstance()メソッドを呼び出し、引数としてInstrumentationオブジェクトを渡すことで、テスト対象のデバイスにアクセスするためのUiDeviceオブジェクトを取得します。
  • UiDeviceインスタンスのfindObject()メソッドを呼び出して、デバイス上に表示されているUIコンポーネント(例えば、フォアグラウンドのカレントビュー)にアクセスするためのUiObjectオブジェクトを取得します。
  • UiObject のメソッドを呼び出すことで、その UI コンポーネントで実行する特定のユーザー インタラクションをシミュレートできます。たとえば、performMultiPointerGesture() を呼び出してマルチタッチ ジェスチャー、setText() を呼び出してテキスト フィールドの編集をシミュレートすることができます。
  • これらのユーザーインタラクションを実行した後、UIに期待される状態や動作が反映されていることを確認します。

明らかに、フレームワークはMainActivityから始まり、ユーザーの使用プロセス全体をシミュレートする必要があります。特定のアクティビティにバインドされず、グローバルなリソースを持つという利点があります。ソース コードは ギットハブ

もちろん、対応するコンポーネントを

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();
}



アプリケーション内の特定のUIコンポーネントにアクセスするには、UiSelectorクラスを使用します。このクラスは、現在表示されている UI の中の特定の要素に対するクエリーを表します。
マッチする要素が複数見つかった場合、レイアウト階層で最初にマッチした要素がターゲットUiObjectとして返されます。UiSelectorを構築する際、複数のプロパティをリンクして検索を最適化することができます。マッチする UI 要素が見つからない場合は、UiAutomatorObjectNotFoundException がスローされます。
childSelector()メソッドを使用すると、複数のUiSelectorインスタンスをネストすることができます。例えば、次のコード例では、現在表示されている UI の最初の ListView を検索するように指定し、その ListView 内を検索して text プロパティを持つ UI 要素を見つける方法をテストしています Apps

UiObject appItem = new UiObject(new UiSelector()
        .className("android.widget.ListView")
        .instance(0)
        .childSelector(new UiSelector()
        .text("Apps")));


テストでUiObjectオブジェクトを取得したら、UiObjectクラスのメソッドを呼び出して、オブジェクトが表すUIコンポーネントに対してユーザーとのインタラクションを実行することができます。指定できるアクションは以下の通りです。

  • click()を使用します。UI要素の可視境界の中心をクリックする。
  • dragTo():このオブジェクトを任意の座標にドラッグします。
  • setText():編集可能なフィールドの内容をクリアした後に、そのテキストを設定します。逆に、clearTextField()メソッドは、編集可能なフィールドの既存のテキストをクリアします。
  • swipeUp():UiObjectを上にスワイプする操作を実行します。同様に、swipeDown()、swipeLeft()、swipeRight()メソッドは、対応する操作を実行します。

FrameLayoutのコンテンツをテストする場合、次のコードのようにUiCollectionを構築する必要があります。

UiCollection videos = new UiCollection(new UiSelector()
        .className("android.widget.FrameLayout"));

// Retrieve the number of videos in this collection
int count = videos.getChildCount(new UiSelector()
        .className("android.widget.LinearLayout"));

// Find a specific video and simulate the user clicking on it
UiObject video = videos.getChildByText(new UiSelector()
        .className("android.widget.LinearLayout"), "Cute Baby Laughing");
video.click();

// Simulate the selection of the checkbox associated with the video
UiObject checkBox = video.getChild(new UiSelector()
        .className("android.widget.Checkbox"));
if(!checkBox.isSelected()) checkbox.click();


スライド可能なビューの場合、UiScrollable クラスを使用すると、ディスプレイ上で垂直または水平方向のスクロールをシミュレートすることができます。これは、UI 要素が画面外にあり、それをビューに配置するためにスクロールする必要がある場合に便利です。
次のコードでは、「設定」メニューをスクロールして「タブレットについて」オプションをクリックする様子をシミュレートしています。

UiScrollable settingsItem = new UiScrollable(new UiSelector()
        .className("android.widget.ListView"));
UiObject about = settingsItem.getChildByText(new UiSelector()
        .className("android.widget.LinearLayout"), "About tablet");
about.click();


5. 概要

さっそくですが、~~~添付の コードリンク