仅当应用程序 100% 完成时,才能在仪器测试后正确清理/拆卸

2024-04-18

我有一堆端到端仪器测试(依赖于 Espresso),它们启动我们的启动器活动,然后在我们的应用程序中导航(最终创建多个活动)。在......的最后each测试我们的@After带注释的拆卸方法执行一些清理工作。

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

这是一个例子:

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.
    }
}

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

那么我怎样才能断言该应用程序已经死了并且消失了before做这个清理工作吗?

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

最终断言后,继续导航回应用程序中的某个中立点(即使用 espresso 注销并返回启动屏幕)。这应该可行,但会添加很多其他步骤every测试。另外,我不确定如果断言失败这是否会起作用。

或者在拆卸中执行某种应用程序终止:

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() docs https://developer.android.com/reference/android/support/test/rule/ActivityTestRule#afterActivityFinished()但我认为这不会起作用multiple活动。


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

使用时AndroidJUnitRunner版本1.0或更高版本,您可以访问 一个名为 Android Test Orchestrator 的工具,它允许您运行 您的应用程序的每个测试都在其自己的 Instrumentation 调用中进行。

每次测试运行后,测试中的应用程序将被自动清理。

build.gradle文件样本AndroidTestOrchestrator启用:

  1. Using AndroidTestOrchestrator带有 Android 支持库 -github链接 https://github.com/Apress/android-espresso-revealed/blob/master/app/build.gradle
  2. Using AndroidTestOrchestrator使用 AndroidX 测试库 -github链接 https://github.com/Apress/android-espresso-revealed/blob/androidx-espresso-revealed/app/build.gradle

Android 官方文档 -link https://developer.android.com/training/testing/junit-runner.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仅当应用程序 100% 完成时,才能在仪器测试后正确清理/拆卸 的相关文章

随机推荐

  • 请求的 dll 执行级别

    我正在开发一个 WinForms 应用程序 Vista Win7 中有一小部分功能需要以管理员身份运行 我了解如何在清单中设置应用程序的requestedExecutionLevel 诀窍是 我不想要求用户以管理员身份运行整个应用程序 而只
  • 有没有简单的 Java REST 教程? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • C++ - 指针传递问题

    有人对如何通过有任何想法吗boost shared ptr 按值或按引用 在我的平台上 32位 sizeof shared ptr 等于 8 个字节 看起来我应该通过引用传递它们 但也许有人有其他意见 做了配置文件 类似的东西 在 C 中
  • 避免从主干视图重新渲染图像和其他内容

    当我重新渲染主干视图时 有什么好方法可以跳过重新渲染图像和谷歌地图等内容 每次重新渲染视图时 我的照片和地图视图都会闪烁得很厉害 这种情况很常见 特别是对于图像 模板引擎从头开始布局布局 这会导致图像标记再次从服务器或从缓存中获取位图 当然
  • 您能解释一下流的概念吗?

    我知道流是字节序列的表示 每个流都提供了向其给定的后备存储读取和写入字节的方法 但流的意义何在 为什么我们与之交互的不是后备存储本身 不管出于什么原因 这个概念并不适合我 我读过很多文章 但我想我需要一个类比或其他东西 选择 流 这个词是因
  • 使用多个存储库构建 VSTS

    我的团队使用 VSTS 进行 Web 项目的 CI CD 为了保持代码分离 我们为前端和后端使用两个单独的存储库 由此提出两个问题 如何设置将两个存储库中的构建工件合并到单个版本中的构建 如何分别从每个存储库触发这个单一构建 发布过程 第一
  • Laravel 在关系模型上按角色名称进行雄辩排序

    我遇到了一个问题 我必须根据模型的关系数据对模型集合进行排序 排序 我已经这样设置了 Models User Team TeamUser Role The TeamUser模型是一个枢轴模型 表 包含user id and team id
  • 悬停时圆形裁剪为圆形边框

    I have an unordered list displayed as a table Each list element contains an image and a name title The image is cropped
  • 如何增加雪花中的可变大小限制?

    我正在尝试通过执行例如来设置变量 SET Variable 1 xxxx 但收到此错误 未完成对 Variable 1 的分配 因为值超出了变量的大小限制 其大小为 309 限制为 256 内部存储大小以字节为单位 另一种方法可以是使用 S
  • 对包含字符串、日期和数字的数组进行排序

    var myArray aaaa 2013 09 25 ssss9 txt aaaa 2013 09 25 ssss8 txt aaaa 2013 09 26 ssss1 txt aaaa 2013 09 25 ssss10 txt aaa
  • 如何在计时器触发后正确调用函数进行单元测试。角度 7、RXJS 6

    在我的 Angular 7 应用程序中 我有一个用于跟踪活动用户任务的服务 在该服务中 计时器每秒运行一次 以检查是否有任何任务在 30 秒内仍未完成 如果发现任何任务已过期 则该任务将通过服务上的事件发射器发出 以便在其他地方处理 当应用
  • Node.js 快速文件服务器(通过 HTTP 的静态文件)

    是否有 Node js 即用工具 安装时使用npm 这将帮助我通过 HTTP 将文件夹内容公开为文件服务器 例如 如果我有 D Folder file zip D Folder file2 html D Folder folder file
  • 从随机像素进行图像插值

    我想问一个关于单通道图像插值的问题 选择单通道只是为了简单起见 否则我正在处理多通道图像 假设有一个纯黑色背景 像素强度为0 的单通道图像 其上有一些强度值非零的像素 我想应用插值算法 用来自相邻非零强度像素的插值填充图像的整个黑色区域 您
  • 有没有办法指定图像的最大高度或宽度?

    我希望图像的高度为 725 或宽度为 500 并保持其纵横比 当我的图像高度超过 725 且厚度小于 500 时 它们会被拉伸以适合 500 的宽度 做这个的最好方式是什么 以下是我现在正在做的事情
  • 反序列化 json 对象数组,其中包含 json 对象

    如何在 C 中反序列化 json 对象数组 这是我的 json id 255521115 user username userinfo id 158 online false 我有这个代码来获取用户名 JsonProperty user p
  • javascript - 按钮需要单击两次才能触发 onclick

    为什么我的按钮需要单击两次才能触发 onclick 事件 stackoverflow 上还有其他一些线程也存在同样的问题 但在我发现的所有线程中 原始发布者将事件处理程序放在函数内 我的代码不是这样的 Html ul li First ch
  • 在 JavaScript 中从具有任意基数的整数生成字符串

    在 JavaScript 中 您可以从数字生成字符串 如下所示 123 toString 36 gt 3f 如果你尝试做任意基础 123 toString 40 You get Uncaught RangeError toString ra
  • 如何使用 bootstrap-multiselect 动态隐藏/显示选项?

    我在用引导多选 http davidstutz github io bootstrap multiselect 为用户提供对两个按键菜单的良好控制 我的第一个菜单叫做groups和其他称为queues 队列中的每个选项都有一个 HTML5
  • Octave-'endfunction' 命令与 'endif' 匹配

    有人可以告诉我我的代码有什么问题吗 sinlaw 150 30 39 8 parse error near line 30 of file endfunction command matched by endif function phi
  • 仅当应用程序 100% 完成时,才能在仪器测试后正确清理/拆卸

    我有一堆端到端仪器测试 依赖于 Espresso 它们启动我们的启动器活动 然后在我们的应用程序中导航 最终创建多个活动 在 的最后each测试我们的 After带注释的拆卸方法执行一些清理工作 我们遇到的问题是 测试完成 成功或失败的断言