Obtenez L'activité actuelle dans Espresso android

dans le cas d'un test qui croise plusieurs activités, y a-t-il un moyen d'obtenir une activité courante?

La méthode

getActivtiy () ne donne qu'une activité qui a été utilisée pour démarrer le test.

j'ai essayé quelque chose comme ci-dessous,

public Activity getCurrentActivity() {
    Activity activity = null;
    ActivityManager am = (ActivityManager) this.getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    try {
        Class<?> myClass = taskInfo.get(0).topActivity.getClass();
        activity = (Activity) myClass.newInstance();
    }
    catch (Exception e) {

    }
    return activity;
}

mais j'obtiens l'objet null.

31
demandé sur stacktry 2014-07-01 22:49:23

10 réponses

dans Espresso, vous pouvez utiliser ActivityLifecycleMonitorRegistry mais il n'est pas officiellement pris en charge, de sorte qu'il peut ne pas fonctionner dans les versions futures.

Voici comment ça marche:

Activity getCurrentActivity() throws Throwable {
  getInstrumentation().waitForIdleSync();
  final Activity[] activity = new Activity[1];
  runTestOnUiThread(new Runnable() {
    @Override
    public void run() {
      java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
      activity[0] = Iterables.getOnlyElement(activities);
  }});
  return activity[0];
}
23
répondu lacton 2016-12-09 15:16:39

si tout ce que vous avez besoin est de faire la vérification par rapport à Activity courant, l'utilisation peut s'entendre avec Espresso une doublure pour vérifier que l'intention prévue a été lancé:

intended(hasComponent(new ComponentName(getTargetContext(), ExpectedActivity.class)));

Espresso vous montrera également les intentions tirées en attendant si ne correspondant pas à la vôtre.

la seule configuration dont vous avez besoin est de remplacer ActivityTestRule par IntentsTestRule dans le test pour lui permettre de garder la trace des intentions de lancement. Et assurez-vous que cette bibliothèque est à votre build.gradle dépendances:

androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1'
25
répondu riwnodennyk 2015-12-18 11:08:27

j'aime la version de @Ryan car elle n'utilise pas de documents internes, mais vous pouvez écrire encore plus court:

private Activity getCurrentActivity() {
    final Activity[] activity = new Activity[1];
    onView(isRoot()).check(new ViewAssertion() {
        @Override
        public void check(View view, NoMatchingViewException noViewFoundException) {
            activity[0] = (Activity) view.getContext();
        }
    });
    return activity[0];
}

s'il vous plaît soyez conscient, bien que cela ne fonctionnera pas lorsque vous effectuez vos tests dans Firebase Test Lab. Qui échoue avec

java.lang.ClassCastException: com.android.internal.policy.DecorContext cannot be cast to android.app.Activity
8
répondu Fabian Streitel 2017-01-01 14:04:40

si vous avez la seule activité dans votre cas d'essai, vous pouvez faire:

1. déclarez-vous test Rule

@Rule
public ActivityTestRule<TestActivity> mActivityTestRule = new ActivityTestRule<>(TestActivity.class);

2. obtenez vous Activity :

mActivityTestRule.getActivity()

C'est un morceau de tarte!

3
répondu Slava 2017-03-04 03:55:17
public static Activity getActivity() {
    final Activity[] currentActivity = new Activity[1];
    onView(allOf(withId(android.R.id.content), isDisplayed())).perform(new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isAssignableFrom(View.class);
        }

        @Override
        public String getDescription() {
            return "getting text from a TextView";
        }

        @Override
        public void perform(UiController uiController, View view) {
            if (view.getContext() instanceof Activity) {
                Activity activity1 = ((Activity)view.getContext());
                currentActivity[0] = activity1;
            }
        }
    });
    return currentActivity[0];
}
2
répondu Ryan 2017-02-16 09:25:01

Les accepté de réponse peut ne pas fonctionner dans de nombreux espresso tests. Ce qui suit fonctionne avec la version 2.2.2 d'espresso et Android compiler/target SDK 27 tournant sur les appareils API 25:

@Nullable
private Activity getActivity() {
    Activity currentActivity = null;

    Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(RESUMED);
    if (resumedActivities.iterator().hasNext()){
        currentActivity = (Activity) resumedActivities.iterator().next();
    }
    return currentActivity;
}
1
répondu pbm 2018-02-06 19:55:49

Je n'ai pu trouver aucune autre solution, alors j'ai fini par avoir à le faire:

Déclarer votre ActivityTestRule :

@Rule
public ActivityTestRule<MainActivity> mainActivityTestRule =
        new ActivityTestRule<>(MainActivity.class);

Déclarer final Activité tableau pour stocker vos activités:

private final Activity[] currentActivity = new Activity[1];

ajouter une méthode helper pour s'enregistrer avec le contexte de l'application pour obtenir des mises à jour du cycle de vie:

private void monitorCurrentActivity() {
    mainActivityTestRule.getActivity().getApplication()
            .registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(final Activity activity, final Bundle savedInstanceState) { }

                @Override
                public void onActivityStarted(final Activity activity) { }

                @Override
                public void onActivityResumed(final Activity activity) {
                    currentActivity[0] = activity;
                }

                @Override
                public void onActivityPaused(final Activity activity) { }

                @Override
                public void onActivityStopped(final Activity activity) { }

                @Override
                public void onActivitySaveInstanceState(final Activity activity, final Bundle outState) { }

                @Override
                public void onActivityDestroyed(final Activity activity) { }
            });
}

ajouter une méthode helper pour obtenir l'activité courante

private Activity getCurrentActivity() {
    return currentActivity[0];
}

ainsi, une fois que vous avez lancé votre première activité, il suffit d'appeler monitorCurrentActivity() et ensuite chaque fois que vous avez besoin d'une référence à l'activité actuelle, vous appelez simplement getCurrentActivity()

1
répondu Billy Brawner 2018-06-08 14:05:24

"151930920 de construire".Grad

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

et, dans votre classe D'essai instrumentée

 @Rule
    public ActivityTestRule<MainActivity> intentsTestRule = new ActivityTestRule<>(MainActivity.class);

    MainActivity mainActivity;

    @Before
    public void setUp() throws Exception {
        mainActivity = intentsTestRule.getActivity(); //now Activity's view gets created
        //Because Activity's view creation happens in UI Thread, so all the test cases, here, are used by UI Thread
    }
0
répondu Uddhav Gautam 2017-08-05 05:16:47
La Solution

proposée par @lacton n'a pas fonctionné pour moi, probablement parce que l'activité n'était pas dans un État qui a été rapporté par ActivityLifecycleMonitorRegistry .

j'ai même essayé Stage.PRE_ON_CREATE toujours pas d'activité.

Note : Je ne pouvais pas utiliser le ActivityTestRule ou IntentTestRule parce que je commençais mon activité en utilisant activitiy-alias et ne faisait aucun sens d'utiliser la classe réelle dans les tests quand je veux tester pour voir si l'alias travail.

ma solution à ce problème était de souscrire à des modifications du cycle de vie par le biais de ActivityLifecycleMonitorRegistry et de bloquer le thread de test jusqu'à ce que l'activité soit lancée:

// NOTE: make sure this is a strong reference (move up as a class field) otherwise will be GCed and you will not stably receive updates.
ActivityLifecycleCallback lifeCycleCallback = new ActivityLifecycleCallback() {
            @Override
            public void onActivityLifecycleChanged(Activity activity, Stage stage) {
                classHolder.setValue(((MyActivity) activity).getClass());

                // release the test thread
                lock.countDown();
            }
         };

// used to block the test thread until activity is launched
final CountDownLatch lock = new CountDownLatch(1);
final Holder<Class<? extends MyActivity>> classHolder = new Holder<>();
instrumentation.runOnMainSync(new Runnable() {
   @Override
    public void run() {
        ActivityLifecycleMonitorRegistry.getInstance().addLifecycleCallback(lifeCycleCallback);
     }
});

// start the Activity
intent.setClassName(context, MyApp.class.getPackage().getName() + ".MyActivityAlias");
context.startActivity(intent);
// wait for activity to start
lock.await();

// continue with the tests
assertTrue(classHolder.hasValue());
assertTrue(classHolder.getValue().isAssignableFrom(MyActivity.class));

Holder est essentiellement un objet enveloppant. Vous pouvez utiliser un tableau ou n'importe quoi d'autre pour capturer une valeur dans la classe anonymous.

0
répondu Bakhshi 2017-11-23 06:01:53

j'ai amélioré la réponse de @Fabian Streitel pour que vous puissiez utiliser cette méthode sans ClassCastException

public static Activity getCurrentActivity() {
    final Activity[] activity = new Activity[1];

    onView(isRoot()).check((view, noViewFoundException) -> {

        View checkedView = view;

        while (checkedView instanceof ViewGroup && ((ViewGroup) checkedView).getChildCount() > 0) {

            checkedView = ((ViewGroup) checkedView).getChildAt(0);

            if (checkedView.getContext() instanceof Activity) {
                activity[0] = (Activity) checkedView.getContext();
                return;
            }
        }
    });
    return activity[0];
}
0
répondu Artem M 2018-09-14 06:54:06