2016-02-03 6 views
15

私は自分のAndroidアプリの計測テストを書こうとしています。Android Instrumentation Testing - UIスレッドの問題

私はいくつかの奇妙なスレッドの問題に遭遇しています。私は解決策を見つけることができません。

私のオリジナルのテスト:

@RunWith(AndroidJUnit4.class) 
public class WorkOrderDetailsTest { 

    @Rule 
    public ActivityTestRule<WorkOrderDetails> activityRule = new ActivityTestRule<>(WorkOrderDetails.class); 

    @Test 
    public void loadWorkOrder_displaysCorrectly() throws Exception { 
     final WorkOrderDetails activity = activityRule.getActivity(); 

     WorkOrder workOrder = new WorkOrder(); 
     activity.updateDetails(workOrder); 

     //Verify customer info is displayed 
     onView(withId(R.id.customer_name)) 
       .check(matches(withText("John Smith"))); 
    } 
} 

この

android.view.ViewRootImpl $ CalledFromWrongThreadExceptionの結果:その景色に触れることができるビュー階層を作成しただけ元のスレッド。

... updateDetails()方法はありません

com.kwtree.kwtree.workorder.WorkOrderDetails.updateDetails(WorkOrderDetails.java:155)

唯一のことは、いくつかのsetText()呼び出しです。

少し調べたところ、UiThreadTestRuleandroid.support.test.annotation.UiThreadTestという注釈をテストに追加すると問題が解決されたようです。

@UiThreadTest:

@RunWith(AndroidJUnit4.class) 
public class WorkOrderDetailsTest { 

    //Note: This is new 
    @Rule 
    public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); 

    @Rule 
    public ActivityTestRule<WorkOrderDetails> activityRule = new ActivityTestRule<>(WorkOrderDetails.class); 

    @Test 
    @UiThreadTest //Note: This is new 
    public void loadWorkOrder_displaysCorrectly() throws Exception { 
     final WorkOrderDetails activity = activityRule.getActivity(); 

     WorkOrder workOrder = new WorkOrder(); 
     activity.updateDetails(workOrder); 

     //Verify customer info is displayed 
     onView(withId(R.id.customer_name)) 
       .check(matches(withText("John Smith"))); 
    } 
} 

java.lang.IllegalStateException:

(注:方法(主に):メインアプリケーションスレッドで呼び出すことができないのすべてをこのスタックトレースのメソッドは私のコードではありません)

私に混合結果を与えてください...ビューを作成した元のスレッドで実行する必要があるが、メインスレッドでは実行できない場合は、どのスレッドを実行する必要がありますか?

私は本当に助けや提案をいただきありがとうございます!

答えて

13

これらの計測テストは、自身のアプリ内で実行されます。これはまた、自身のスレッドで実行されることを意味します。

実際のアプリと一緒にインストールするものとしてインストゥルメンテーションを考える必要があるため、可能な対話は「制限されています」。

アプリケーションのUIThread /メインスレッドからすべてのビューメソッドを呼び出す必要があるため、計測スレッドからactivity.updateDetails(workOrder);を呼び出すと、ではなく、アプリケーションメインスレッドとなります。このため、例外がスローされます。

あなたはちょうどあなたがあなたのテストを実行して動作するはずこれにより

activity.runOnUiThread(new Runnable() { 
    public void run() { 
     activity.updateDetails(workOrder); 
    } 
} 

を使用して、別のスレッドからのアプリの内部でそれを呼び出した場合はどうなるのようなあなたのメインスレッド上でテストする必要があるコードを実行することができます。

あなたが受け取っている不正な州の例外は、あなたのルールとのやりとりのためと思われます。 documentation

この注釈が存在する場合、計測方法は使用できないことに注意してください。

アクティビティを開始/取得する場合は、@Beforeも有効です。あなたがUiThreadTestRule.runOnUiThread(Runnable)の助けを借りて、メインUIスレッド上で、あなたのテストの一部を実行することができます

+1

' runOnUiThread'のアプローチが働いていたwaitForIdleSync(); '。。 '@ Before'アプローチは残念ながらうまくいきませんでした。助けてくれてありがとう! – Khalos

12

@Rule 
public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); 

@Test 
public void loadWorkOrder_displaysCorrectly() throws Exception { 
    final WorkOrderDetails activity = activityRule.getActivity(); 

    uiThreadTestRule.runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      WorkOrder workOrder = new WorkOrder(); 
      activity.updateDetails(workOrder); 
     } 
    }); 

    //Verify customer info is displayed 
    onView(withId(R.id.customer_name)) 
      .check(matches(withText("John Smith"))); 
} 

ほとんどの場合、UiThreadTestでテストメソッドに注釈を付けることが簡単です、しかし、それは他のエラーが発生する場合がありjava.lang.IllegalStateException: Method cannot be called on the main application thread (on: main)などです。

注、現在のJUnit制限によるもの、BeforeAfterで注釈が付け方法もUIスレッド上で実行されます。

FYRは、ここにUiThreadTestさんのJavadocからの引用です。 問題がある場合は、runOnUiThread(Runnable)の使用を検討してください。

上記UiThreadTest(パッケージandroid.support.test.annotation)(UiThreadTest(パッケージandroid.test))とは異なるのでご注意下さい。

0

受け入れられた答えは、何が完璧に進行しているかを説明しています。

さらに、エスプレッソのUIに触れる方法が好奇心に溢れている場合などに、 perform(ViewActions ...)は同じことをする必要はありません。それは後で私たちのためにやってしまうからです。

あなたがperform(ViewActions ...)に従うならば、あなたはそれが(android.support.test.espresso.ViewInteractionで)次の操作を行って終わるでしょう:

private void runSynchronouslyOnUiThread(Runnable action) { 
    ... 
    mainThreadExecutor.execute(uiTask); 
    ... 
} 

mainThreadExecutor@MainThreadでアノテート自身であること。

つまり、エスプレッソも、受け入れられた回答にDavidが記述したのと同じルールでプレイする必要があります。

9

受け入れられる回答は推奨されていません。今、これを行うための正しい方法は単純です: `getInstrumentation()と組み合わせると

@Test 
@UiThreadTest 
public void myTest() { 
    // ... 
} 
関連する問題