仅当应用程序100%完成后,才能在工具测试后正确清理/拆除 [英] Properly cleanup / teardown after instrumentation test only when app is 100% finished

查看:95
本文介绍了仅当应用程序100%完成后,才能在工具测试后正确清理/拆除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多端到端的测试(依赖于Espresso),它们启动了启动器活动,然后浏览了我们的应用程序(最终创建了多个活动).在 每个 的测试结束时,我们的@After带注释的拆卸方法将执行一些清理操作.

I have a bunch of end-to-end instrumentation tests (relying on Espresso) that start our launcher activity, then navigate throughout our app (eventually creating several activities). At the end of each test our @After annotated tear down method performs some cleanup.

我们遇到的问题是,在测试完成(成功或失败的断言)之后,应用程序仍在运行",因此某些清理操作实际上导致应用程序崩溃.如果断言成功,这将导致误报,或者隐藏测试失败(我们只看到崩溃而不是失败的断言).

The problem we have is that after the test finishes (successful or failed assertion) the app is still "running", so some of the cleanup is actually causing the app to crash. This is either resulting in false positives if the assert was successful, or hiding the test failure (we only see the crash not the failed assertion).

这是一个例子:

import android.app.Instrumentation;
import android.content.Intent;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ActivityTestRule;

import com.example.SplashActivity;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import static android.support.test.InstrumentationRegistry.getInstrumentation;

public class ExampleTest {

    @Rule
    public ActivityTestRule<SplashActivity> splashActivityTestRule
            = new ActivityTestRule<>(SplashActivity.class, true, false);

    Instrumentation.ActivityMonitor splashActivityMonitor;

    @Before
    public void setUp() {
        splashActivityMonitor = new Instrumentation.ActivityMonitor(SplashActivity.class.getName(), null, false);
        getInstrumentation().addMonitor(splashActivityMonitor);
    }

    @Test
    public void someTest() throws Exception {
        // ... other test-specific setup before starting splash activity

        // start first activity
        splashActivityTestRule.launchActivity(new Intent());

        // a bunch of espresso steps that result in several other activities
        // ... creating and adding Instrumentation.ActivityMonitor for each one

        // assert something
    }

    @After
    public void tearDown() {
        // clear shared prefs to prepare for next test
        PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getTargetContext())
                .edit()
                .clear()
                .apply();

        // At this point the app is still running. Maybe a UI is still loading that was not relevant to the test, 
        // or some mock web request is in flight. But at some point after the final assert in our test, the app needs
        // to get something from shared prefs, which we just cleared, so the app crashes.
    }
}

如您所见,在拆解方法期间,该应用程序仍在运行.我们在此处对应用程序状态进行的任何更改都可能导致应用程序崩溃.

As you can see, the app is still running during the tear down method. Any changes we make to the state of the app here may cause the app to crash.

那么我该如何断言该应用程序已经死了并且在进行清理之前 ?

So how can I assert that the app is dead and gone before doing this cleanup?

我想出了一些可能(但很丑陋)的解决方案:

Some possible (but ugly) solutions I've come up with:

在最终断言之后,继续导航回应用程序中的某个中性点(即使用espresso登出并返回初始屏幕).这应该可以,但是会为每次测试添加很多其他步骤.另外,我不确定断言失败是否可以解决此问题.

After the final assert, continue to navigate back to some neutral point in the app (i.e use espresso to logout and return to splash screen). This should work but it'll add a lot of other steps to every test. Also I'm not sure this will work if the assert fails.

或者在拆解中执行某种应用终止功能:

Or perform some sort of app kill in the teardown:

public void tearDown() {
    // finish all tasks before cleaning up
    ActivityManager activityManager =
            (ActivityManager) InstrumentationRegistry.getTargetContext().getSystemService(Context.ACTIVITY_SERVICE);

    List<ActivityManager.AppTask> appTasks = activityManager.getAppTasks();
    for (ActivityManager.AppTask appTask : appTasks) {
        appTask.finishAndRemoveTask();
    }

    // clear shared prefs to prepare for next test
    PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getTargetContext())
            .edit()
            .clear()
            .apply();
}


更新:


Update:

我知道我可以使用ActivityTestRule.afterActivityFinished() 文档,但我认为这不适用于多个活动.

I know I can use ActivityTestRule.afterActivityFinished() docs but I don't think this will work for multiple actvities.

推荐答案

可以使用AndroidTestOrchestrator解决您描述的问题.来自官方的Android文档:

The problem you described can be solved by using AndroidTestOrchestrator. From the official Android documentation:

使用AndroidJUnitRunner 1.0或更高版本时,您可以访问 到名为Android Test Orchestrator的工具中,该工具可让您运行 您的应用程序的每个测试均在其自己的检测工具"调用中进行.

When using AndroidJUnitRunner version 1.0 or higher, you have access to a tool called Android Test Orchestrator, which allows you to run each of your app's tests within its own invocation of Instrumentation.

每个测试自动运行后,将清理被测应用程序.

Application under test will be cleaned after each test run automatically.

build.gradle文件示例:

  1. AndroidTestOrchestrator与Android支持库一起使用- github链接
  2. AndroidTestOrchestrator与AndroidX测试库一起使用-
  1. Using AndroidTestOrchestrator with Android support library - github link
  2. Using AndroidTestOrchestrator with AndroidX Test library - github link

Android官方文档-链接.

Official Android documentation - link.

这篇关于仅当应用程序100%完成后,才能在工具测试后正确清理/拆除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆