gpt4 book ai didi

android - 如何将 Jake Wharton 的机器人模式实现到 Espresso UI 测试中?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:19:23 25 4
gpt4 key购买 nike

Jake Wharton 发表了精彩的演讲,他提出了一些巧妙的方法来改进我们的 UI 测试,方法是从测试中抽象出我们如何执行 UI 的细节:https://news.realm.io/news/kau-jake-wharton-testing-robots/

他给出的一个示例是如下所示的测试,其中 PaymentRobot 对象包含有关如何将付款金额和收款人输入 UI 的详细信息。把那个地方放在一个地方很有意义,所以当 UI 不可避免地发生变化时(例如重命名字段 ID,或从 TextEdit 切换到 TextInputLayout),它只需要在一个地方更新而不是整个系列的测试。它还使测试更加简洁和可读。他建议使用 Kotlin 使它们更简洁。我不使用 Kotlin,但仍想从这种方法中受益。

@Test public void singleFundingSourceSuccess {
PaymentRobot payment = new PaymentRobot();
ResultRobot result = payment
.amount(42_00)
.recipient("foo@bar.com")
.send();
result.isSuccess();
}

他概述了 Robot 类的结构,带有明确的 isSuccess() 响应,返回另一个 Robot,它要么是下一个屏幕,要么是当前屏幕的状态:

class PaymentRobot {
PaymentRobot amount(long amount) { ... }
PaymentRobot recipient(String recipient) { .. }
ResultRobot send() { ... }
}

class ResultRobot {
ResultRobot isSuccess() { ... }
}

我的问题是:

  • Robot 如何与 Activity/Fragment 交互,特别是在何处实例化?我希望运行者在测试中会发生这种情况,但他的例子似乎表明并非如此。该方法看起来可能非常有用,但我不知道如何在实践中实现它,无论是针对单个 Activity/Fragment 还是针对它们的序列。
  • 如何扩展此方法,以便 isSuccess() 方法可以处理各种情况。例如如果我们正在测试登录屏幕,isSuccess() 如何处理各种预期结果,例如:身份验证成功、API 网络故障和身份验证失败(例如 403 服务器响应)?理想情况下,API 将在 Retrofit 后面进行模拟,并且每个结果都通过端到端 UI 测试进行测试。

除了 Jake 的概述演讲之外,我找不到任何实现示例。

最佳答案

我完全误解了 Espresso 的工作原理,这导致我更加困惑如何将它应用于页面对象模式。我现在看到 Espresso 不需要任何类型的对被测 Activity 的引用,而只是在运行器规则的上下文中运行。对于其他苦苦挣扎的人,这是一个充实的示例,将机器人/页面对象模式应用于带有用户名和密码字段的登录屏幕上的验证测试,我们正在测试其中一个字段是否显示错误消息空:

LoginRobot.java(抽象登录 Activity 的自动化)

public class LoginRobot {

public LoginRobot() {
onView(withId(R.id.username)).check(matches(isDisplayed()));
}

public void enterUsername(String username) {
onView(withId(R.id.username)).perform(replaceText(username));
}

public void enterPassword(String password) {
onView(withId(R.id.password)).perform(replaceText(password));
}

public void clickLogin() {
onView(withId(R.id.login_button)).perform(click());
}

}

(注意构造函数正在测试以确保当前屏幕是我们期望的屏幕)

LoginValidationTests.java:

@LargeTest
@RunWith(AndroidJUnit4.class)
public class LoginValidationTests {

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

@Test
public void loginPasswordValidationTest() {
LoginRobot loginPage = new LoginRobot();
loginPage.enterPassword("");
loginPage.enterUsername("123");
loginPage.clickLogin();
onView(withText(R.string.login_bad_password))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
}

@Test
public void loginUsernameValidationTest() {
LoginRobot loginPage = new LoginRobot();
loginPage.enterUsername("");
loginPage.enterPassword("123");
loginPage.clickLogin();
onView(withText(R.string.login_bad_username)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
}

}

像这样抽象机制来自动化 UI 避免了测试之间的大量重复,也意味着更改不太可能需要在许多测试中反射(reflect)出来。例如如果布局 ID 发生变化,它只需要在机器人类中更新,而不是每个引用该字段的测试。测试也明显更短且更易读。

机器人方法,例如登录按钮方法,可以返回链中的下一个机器人(即在登录屏幕后对 Activity 进行操作的机器人)。例如LoginRobot.clickLogin() 返回一个 HomeRobot(用于应用程序的主屏幕)。

我已将断言放入测试中,但如果在许多测试中重复使用断言,将一些抽象到机器人中可能是有意义的。

在某些情况下,使用 View 模型对象来保存一组在测试中重复使用的假数据可能是有意义的。例如如果测试一个包含多个字段的注册屏幕,该屏幕由许多测试操作,那么构建一个工厂来创建一个包含名字、姓氏、电子邮件地址等的 RegistrationViewModel 可能是有意义的,并在测试中引用它而不是复制它代码。

关于android - 如何将 Jake Wharton 的机器人模式实现到 Espresso UI 测试中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43847448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com