【问题标题】:Espresso toast test fails if second test is added如果添加第二个测试,则 Espresso 吐司测试失败
【发布时间】:2017-12-01 15:51:34
【问题描述】:

我有一个 Activity 可以根据 Web 服务调用返回的状态显示不同的 toast。

我正在编写一个测试类,我的第一个测试测试是否在出现网络错误时显示其中一个 toast。下面是测试类:

@RunWith(AndroidJUnit4.class)
public class LoginActivityTest extends BaseTest {

    @Rule
    public final ActivityTestRule<LoginActivity> login = new ActivityTestRule(LoginActivity.class, true);

    @Test
    public void noNetwork() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                login.getActivity().onEventMainThread(new LoginResp(CopiaWebServiceClient.ResponseStatus.NETWORK_ERROR));
            }
        });

        onView(withText(R.string.toast_no_network_connection))
            .inRoot(withDecorView(not(is(login.getActivity().getWindow().getDecorView()))))
            .check(matches(isDisplayed()));
    }
}

所以noNetwork 测试调用LoginActivityonEventMainThread(LoginResp loginResp) 方法(这需要在UI 线程上运行,因此我使用runOnMainSync)并带有网络错误状态以提示它显示预期的toast_no_network_connection吐司。

此测试有效并运行并成功通过。

这是我的问题

如果我向测试类添加第二个测试,第二个测试会失败。这是第二个测试,与第一个测试相同,只是它将不同的错误状态传递给 onEventMainThread(LoginResp loginResp),以便显示不同的 toast:

    @Test
    public void serverErr() {
       InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                login.getActivity().onEventMainThread(new LoginResp(CopiaWebServiceClient.ResponseStatus.HTTP_SERVER_ERROR));
            }
        });

        onView(withText(R.string.toast_operation_failure_app_error))
            .inRoot(withDecorView(not(is(login.getActivity().getWindow().getDecorView()))))
            .check(matches(isDisplayed()));
    }

第二次测试失败,输出:android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with string from resource id: &lt;2131689669&gt;[toast_operation_failure_app_error] value: Sorry, failure to complete operation due to application error.

但是,在运行测试时观看模拟器,我看到了最初的toast_no_network_connection toast(第一次测试预期),然后是toast_operation_failure_app_error toast(第二次测试预期)。为什么第二次测试失败了?

这与一个接一个地运行的测试有关,因为当我注释掉第一个测试时,第二个测试通过了。

LoginActivity 中的 onEventMainThread(LoginResp loginResp) 方法具有以下代码,可根据状态显示适当的 toast:

switch (status) {

        case HTTP_UNAUTHORIZED:
            DialogCreator.createAlertDialog(this, getString(R.string.dialog_msg_login_fail)).show();

            break;

        case NETWORK_ERROR:
            Toast.makeText(this, getString(R.string.toast_no_network_connection), Toast.LENGTH_SHORT).show();

            break;

        default:
            Toast.makeText(this, getString(R.string.toast_operation_failure_app_error), Toast.LENGTH_SHORT).show();

    }

调试测试我看到第一个测试按预期进入 NETWORK_ERROR 情况,第二个测试按预期进入 switch 语句的 default 部分。

【问题讨论】:

  • “这与一个接一个地运行的测试有关,因为当我注释掉第一个测试时,第二个测试通过了”——您是否尝试过颠倒测试的顺序? IOW,总是第二次测试失败还是总是R.string.toast_operation_failure_app_error 失败?我从来没有对 Toasts 进行 Espresso 测试(我很惊讶这是可能的,因为 View 并没有严格地绑定到你的 UI,上次我检查过)
  • 是的,我颠倒了测试的顺序,发现第二个测试总是失败,所以toast_no_network_connection如果第二个就会失败。
  • 嗯...不知道你能做什么。您可以尝试将这些合并到一个 @Test 方法中,看看您会得到什么结果。我不确定为什么第二个活动实例会出现第一个没有的问题,但是对这些使用单个 @Test 方法会让您使用单个活动实例,这可能会让您解决问题。跨度>
  • 是的,我颠倒了测试的顺序,发现第二个测试总是失败,所以toast_no_network_connection如果第二个就会失败。当 second 测试失败时,失败的 NoMatchingViewException 消息中包含的视图层次结构包含来自 first 测试的 Toast。所以第一个测试的Toast 似乎在“闲逛”,可以这么说,在它运行之后。
  • “所以第一个测试的 Toast 似乎在“徘徊”,可以这么说,在它运行之后”——它将在 Toast.LENGTH_SHORT 停留一段时间。你的第二个Toast 直到那时才会显示。

标签: android android-espresso


【解决方案1】:

在进一步玩了一些测试之后,我选择了 Eirik W 在Espresso checking if toasts are displayed (one on top of another) 的回答中建议的方法

我稍微更改了我的生产代码,将 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 注释的 Toast 成员添加到 LoginActivity 以启用 LoginActivityTest 中的 @After 注释方法,在每次测试后取消任何显示的 toast。

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 2015-02-03
    • 2019-10-23
    相关资源
    最近更新 更多