Android Instrumentation de Test - Thread d'INTERFACE utilisateur Questions
Je suis en train d'écrire une Instrumentation de Test pour mon application Android.
Je suis en cours d'exécution dans d'étranges problèmes de threading et je n'arrive pas à trouver une solution.
Mon Premier Test:
@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")));
}
}
Ce qui a entraîné une
android.vue.ViewRootImpl$CalledFromWrongThreadException: Seul le thread qui a créé un point de vue de la hiérarchie peut toucher son point de vue.
...
com.kwtree.kwtree.l'ordre du travail.WorkOrderDetails.updateDetails(WorkOrderDetails.java:155)
La seule chose que l' updateDetails()
méthode n'est quelques setText()
appels.
Après avoir cherché un peu, il semble que l'ajout d'un UiThreadTestRule
et android.support.test.annotation.UiThreadTest
annotation à mon test de résoudre le problème.
@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: Méthode ne peut être appelée sur le thread principal de l'application (sur: principal)
(Remarque: Toutes les méthodes dans cette trace de la pile ne sont pas de mon code)
Il semble être en me donnant des résultats mitigés... Si il doit être exécuté sur le thread d'origine qui a créé la vue, mais ne peut pas s'exécuter sur le thread principal, ce fil doit-il être géré sur?
J'apprécierais vraiment de l'aide ou des suggestions!
Vous devez vous connecter pour publier un commentaire.
Ceux de l'instrumentation de tests s'exécutent à l'intérieur de leur propre app. Cela signifie également qu'ils s'exécutent dans leur propre thread.
Vous devez penser à votre instrumentation comme quelque chose de vous installer à côté de votre application, de sorte que vos interactions possibles sont "limitées".
Vous avez besoin d'appeler toutes les méthodes de vue de l'UIThread /thread principal de l'application, afin de l'appelant
activity.updateDetails(workOrder);
de vos instruments thread est pas le thread principal de l'application. C'est pourquoi, l'exception est levée.Il vous suffit d'exécuter le code, vous devez le tester sur votre thread principal comme vous le feriez si vous étiez en appelant à l'intérieur de votre application à partir d'un autre thread à l'aide de
Avec cette exécution de votre test devrait fonctionner.
Illégale de l'état d'exception vous recevoir semble être à cause de son interaction avec la règle. Le la documentation états
Si vous commencez /obtenez votre activité dans
@Before
il devrait également fonctionner.runOnUiThread
approche travaillé lorsqu'il est combiné avecgetInstrumentation().waitForIdleSync();
. Le@Before
approche ne fonctionne pas malheureusement. Merci pour l'aide!Vous pouvez exécuter la partie de votre test sur le main thread d'INTERFACE utilisateur à l'aide de
UiThreadTestRule.runOnUiThread(Runnable)
:Dans la plupart des cas, il est plus simple d'annoter la méthode de test à
UiThreadTest
, cependant, il peut encourir d'autres erreurs commejava.lang.IllegalStateException: Method cannot be called on the main application thread (on: main)
.ARY, voici une citation de
UiThreadTest
's Javadoc:Veuillez noter
UiThreadTest
(paquetandroid.support.test.annotation
) mentionné ci-dessus est différent (UiThreadTest
(paquetandroid.test
)).Accepté la réponse est aujourd'hui obsolète
La façon la plus simple d'y parvenir est d'utiliser simplement
UiThreadTest
Android.Test.UIThreadTest is deprecated as of API 24: Android 7.0 (Nougat)
, note que ce n'est pas la même annotation. Cette réponse est d'utiliser le support d'annotation. Qui ne peut pas être résolu pour moimyTest
où avez -activity
viennent? C'est ce que je suis coincé sur.La accepté de répondre décrit ce qui se passe à la perfection.
Comme une outre, au cas où quelqu'un est curieux de savoir pourquoi Espresso méthodes qui touche l'INTERFACE utilisateur par exemple
perform(ViewActions ...)
n'avez pas besoin de faire la même chose, c'est tout simplement parce qu'ils finissent par le faire plus tard pour nous.Si vous suivez
perform(ViewActions ...)
vous trouverez qu'il finit par faire ce qui suit (dansandroid.support.test.espresso.ViewInteraction
):Que
mainThreadExecutor
est lui-même annoté avec@MainThread
.En d'autres termes, l'Espresso a aussi besoin de jouer selon les mêmes règles décrites par David sur la accepté de répondre.