- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想知道如何使用 Espresso 重新运行失败的测试。我认为它比常见的 JUnit 测试用例要复杂一些,因为您需要在测试开始之前恢复应用程序中的状态。
我的方法是创建我自己的 ActivityTestRule,所以我只是从这个类中复制了整个代码并将其命名为 MyActivityTestRule。
在仪器测试的情况下,规则还需要我们希望如何开始我们的 Activity 的信息。我更喜欢自己启动它,而不是让环境为我启动它。例如:
@Rule
public MyActivityTestRule<ActivityToStartWith> activityRule = new MyActivityTestRule<>(
ActivityToStartWith.class, true, false
);
所以我也在@Before注解方法中启动了我的activity:
@Before
public void setUp() throws Exception {
activityRule.launchActivity(new Intent());
}
并在@After 注解方法中进行清理:
@After
public void tearDown() throws Exception {
cleanUpDataBaseAfterTest();
returnToStartingActivity(activityRule);
}
这些方法 - setUp()、tearDown() 在每次测试运行之前/之后必须调用 - 以确保测试开始期间的应用状态正确。
在 MyActivityTestRule 中,到目前为止我做了一些修改。首先是更改应用方法:
@Override
public Statement apply(final Statement base, Description description) {
return new ActivityStatement(super.apply(base, description));
}
这对我来说是个未知数,因为放在 ActivityTestRule 中的 ActivityStatement 有 super.apply 方法,所以它也在 UiThreadStatement 中包装了测试语句:
public class UiThreadStatement extends Statement {
private final Statement mBase;
private final boolean mRunOnUiThread;
public UiThreadStatement(Statement base, boolean runOnUiThread) {
mBase = base;
mRunOnUiThread = runOnUiThread;
}
@Override
public void evaluate() throws Throwable {
if (mRunOnUiThread) {
final AtomicReference<Throwable> exceptionRef = new AtomicReference<>();
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
try {
mBase.evaluate();
} catch (Throwable throwable) {
exceptionRef.set(throwable);
}
}
});
Throwable throwable = exceptionRef.get();
if (throwable != null) {
throw throwable;
}
} else {
mBase.evaluate();
}
}
}
无论我用我的测试做什么,我永远无法创建 case mRunOnUiThread boolean 值为真。如果在我的测试用例中,将出现带有注释 @UiThreadTest 的测试,那将是正确的——或者这就是我从代码中理解的内容。但它从来没有发生过,我不使用任何类似的东西所以我决定忽略这个 UiThreadStatement 并将 MyActivityTestRule 更改为:
@Override
public Statement apply(final Statement base, Description description) {
return new ActivityStatement(base);
}
我的测试用例运行没有任何问题。多亏了我剩下的一切——环绕 mBase.evaluate() 的是:
private class ActivityStatement extends Statement {
private final Statement mBase;
public ActivityStatement(Statement base) {
mBase = base;
}
@Override
public void evaluate() throws Throwable {
try {
if (mLaunchActivity) {
mActivity = launchActivity(getActivityIntent());
}
mBase.evaluate();
} finally {
finishActivity();
afterActivityFinished();
}
}
}
一般来说,仅当我在 ActivityTestRule 构造函数的第三个参数中设置值 true 时,才会调用 launchActivity。但是我自己在 setUp() 中启动测试,所以它永远不会发生。
据我了解,mBase.evaluate() 在@Test 注释方法中运行我的代码。它还会在抛出 throwable 期间停止测试用例。这意味着我可以捕获它并重新启动它 - 就像那里提出的那样: How to Re-run failed JUnit tests immediately?
好吧,我做了类似的事情:
public class ActivityRetryStatement extends Statement {
private final Statement mBase;
private final int MAX_RUNS = 2;
public ActivityRetryStatement(Statement base) {
mBase = base;
}
@Override
public void evaluate() throws Throwable {
Throwable throwable = null;
for (int i = 0; i < MAX_RUNS; i++) {
try {
mBase.evaluate();
// if you reach this lane that means evaluate passed
// and you don't need to do the next run
break;
} catch (Throwable t) {
// save first throwable if occurred
if (throwable == null) {
throwable = t;
}
// my try that didn't work
launchActivity(testInitialIntent);
// I've returned test to starting screen but
// mBase.envaluate() didn't make it run again
// it would be cool now to:
// - invoke @After
// - finish current activity
// - invoke @Before again and start activity
// - mBase.evaluate() should restart @Test on activity started again by @Before
}
}
finishActivity();
afterActivityFinished();
// if 1st try fail but 2nd passes inform me still that there was error
if (throwable != null) {
throw throwable;
}
}
}
所以 catch block 中的那些评论是我不知道该怎么做的部分。我尝试按照我在 setUp() 中使用的 Intent 执行 launchActivity 以第一次运行测试。但是 mBase.evaluate() 没有让它使用react(测试用例没有再次进行) - 什么都没发生 + 我认为它不会真正拯救我。我缺少我在@SetUp 中做的一些启动,它没有被再次调用。我真的很想找到一种方法来重新正确地重新启动整个测试生命周期@Before @Test @After。也许从代码中调用 Instrumentation 或 TestRunner。
关于如何做到这一点有什么想法吗?
最佳答案
您可以使用 https://github.com/AdevintaSpain/Barista用于重新运行失败测试的库。
您可以在此处查看有关处理不稳定测试的更多详细信息:https://github.com/AdevintaSpain/Barista#dealing-with-flaky-tests
关于java - 如何在 Espresso 中重新运行失败的测试? - 头脑 Storm ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35921423/
这个问题在这里已经有了答案: How does Scala's apply() method magic work? (3 个回答) 9年前关闭。 假设我在 scala 中有一个 MyList 类,其
这个问题在这里已经有了答案: What is a non-capturing group in regular expressions? (18 个回答) Reference - What does
这个问题是针对嵌入式系统的! 我有以下选项来初始化一个对象: Object* o = new Object(arg); 这会将对象放入堆中并返回指向它的指针。我不喜欢在嵌入式软件中使用动态分配。 Ob
我自己搜索过,没能成功的正则表达式。 我有一个 html 文件,其中包含 [] 之间的变量我想把每一个字都写进去。 [client_name][client_company] [cl
我是 Python 新手。我不明白为什么这段代码不起作用: reOptions = re.search( "[\s+@twitter\s+(?P\w+):(?P.*?)\s+]", d
在过去 7 个月左右的时间里,我几乎一直在使用 .NET C# 进行编程。在那之前,我的大部分编程都是用 C++(从学校里学的)。在工作中,我可能需要在接下来的几个月里做一大堆 C 语言。我对 C 的
我是 RE 的新手,我正在尝试获取歌词并分离出歌词标题、和声和主唱: 下面是一些歌词的例子: [Intro] D.A. got that dope! [Chorus: Travis Scott] Ic
这可能是不可能的,但我想检查是否可以用一种简单的方式表达这样的事情: // obviously doesn't work class Foo : IFoo where T: Bar {
我们的应用程序中有“user”和“study”实体,存储在它们各自的表中。一项研究代表一种研究和已收集的数据。它们是多对多的关系,所以我们需要一个链接表:studies_users。 我们为用户分配角
将测试条件添加到 Visual Studio 2010 数据库单元测试(对于 SQL Server 2008)时,这些条件称为例如rowCountCondition1、rowCountConditio
在模拟器上,我可以从设置中卸载 SD 卡。 然后我可以将它安装到我的操作系统上,然后正常卸载它。 我一直无法弄清楚如何在模拟器上重新安装它(无需重新启动)。 提示: adb 命令 remount 是无
假设在一个分支上执行了一系列提交,但该分支尚未与主干重新同步。是否可以从提交中生成全局补丁?是否可以从一系列提交中生成“分组”补丁?如果是,如何? 最佳答案 svn diff -rXXX:YYY UR
在某些情况下,我想在我的应用程序中锁定调整大小功能,为此我尝试对属性进行数据绑定(bind),并且不允许在某些情况下更改它,但没有成功。 有没有办法这样做? 这是我不成功的尝试: XAML: Vie
当我的计算机连接多个显示器时,我可以检测它们,并根据从获取的值设置位置来向它们绘制图形 get(0, 'MonitorPositions') 但是,当我在 MATLAB 运行时断开监视器时,此属性不会
我们有一个grails应用程序,该应用程序在grails数据库中存储了各种域对象。该应用程序连接到第二个数据库,运行一些原始sql,并在表中显示结果。它基本上是一个报告服务器。 我们通过在DataSo
无法比较来自不同容器的迭代器(参见这里的示例: https://stackoverflow.com/a/4664519/225186 )(或者从技术上讲,它不需要有意义。) 这就提出了另一个问题,来自
我有以下情况: 家长 Activity : ParentActivityClass { private Intent intent; @Override public void onCreate(Bu
我经常将元素与附加功能 Hook ,例如: $('.myfav').autocomplete(); $('.myfav').datepicker(); $('.myfav').click(somefu
因此,我将 tooltipster.js 库用于工具提示,并尝试更改工具提示在不同屏幕尺寸上的默认距离。 所以这是默认的 init 的样子: $(inputTooltipTrigger).tool
我在 ARM7 嵌入式环境中工作。我使用的编译器不支持完整的 C++ 功能。它不支持的一项功能是动态类型转换。 有没有办法实现dynamic_cast<>() ? 我使用 Google 寻找代码,但到
我是一名优秀的程序员,十分优秀!