安卓Espresso和账户选择器

7
我在使用Espresso进行仪表化测试时遇到了困难。我的应用程序中有一个活动,在启动时会弹出帐户选择器(主活动)。如果客户点击取消(在对话框中),选择器将再次弹出;如果用户点击添加,则会在活动结果中选择结果。
我不知道如何使用Espresso创建一个简单的测试,其中包括该选择器。当我使用MainActivity创建仪器化测试时,我收到以下消息:无阶段RESUMED活动...
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity>{
    MainActivity myActivity;
    public MainActivityTest(){
        super(MainActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        getActivity();
    }

    public void testAccountPicker(){
        onView(withText("Choose an account")).check(matches(isDisplayed()));
    }
}

有人遇到过类似的问题吗?提前感谢您的答案。

你能发布一下你的活动生命周期方法吗? - Bolhoso
Bolhoso,我在onCreate方法中加入了以下代码: Intent googlePicker = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null); startActivityForResult(googlePicker, Utils.PICK_ACCOUNT_REQUEST); 并且添加了账户选择的逻辑。其他生命周期方法没有改变。 - DI_one
3个回答

3
那很困难 :). 这里的问题在于一旦流程离开您的应用程序(Google帐户选择器是外部应用程序),Espresso测试就会结束。Account Picker是来自包com.google.android.gms的活动,因此是外部的。一旦它启动,您的测试就完成了,您将无法匹配对话框中的任何内容。
您有三种可能的解决方案使测试可行:
  • 在您的应用程序上使用类路径替换以伪造意图;或
  • 修复您的应用程序“可测试性”;或
  • 使用依赖注入,例如Dagger
我将展示如何使用类路径替换。这种技术非常简单:您应该将Intent创建隔离在一个单独的类中,比如说IntentsFactory,并在测试期间覆盖该类。
假设您的工厂位于com.yourapp.factories.IntentsFactory中,并且它是这样的:
public class IntentsFactory {
    public static Intent getAccountPickerIntent (Context context) {
        return AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
    }
}

你应该在测试应用程序中创建一个同名的包和方法(例如,com.yourapp.tests),但返回一个不同的Intent,即模拟/虚拟的Intent:
public class IntentsFactory {
    public static Intent getAccountPickerIntent (Context context) {
        return new Intent(context, MyDummyAccountPickerActivity.class);
    }
}

每次执行测试时,它们将使用类路径中“最近”的类,也就是来自测试的IntentsFactory。流程将转到您项目中的一个类,而不是返回将流程发送到另一个应用程序的意图,并且Espresso不会结束测试。
唯一的注意事项是,您必须创建MyDummyAccountPickerActivity,它将返回与框架类返回的类似的结果和Bundle。该活动应存在于您应用程序的清单中,并且您将不得不指示您的模拟器Dalvik运行时允许使用以下命令行进行类路径(请查看此thisthis链接)替换:
adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
adb shell stop installd
adb shell start installd

并执行您的测试。

我遇到了类似的问题,需要测试相机,这在Espresso论坛中有详细讨论。


1
一如既往地,我总是在“昨天就需要完成”的情况下将测试暂停了一段时间。但我明白你的建议,一定会尝试的。抱歉回复晚了。谢谢。 - DI_one

1
似乎你需要在根视图上进行操作,而在你的情况下是“账户选择器”。尝试这样做:
public void testAccountPicker(){
    onView(withText("Choose an account"))
        .inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView()))))
        .check(matches(isDisplayed()));
}

嗨,Denys,我仍然收到错误消息:“在阶段RESUMED中没有活动。您是否忘记启动活动(test.getActivity()或类似)?” - DI_one
好的,你的应用程序中没有自定义帐户选择器,而是使用了Google帐户选择器,对吗?如果是这样,我认为你无法处理它,因为你在应用程序之外。请在android-test-kit-discuss Google组中提出此问题-https://groups.google.com/forum/#!forum/android-test-kit-discuss。 - denys
是的,你说得对。我使用谷歌账户选择器而不是我的自己的账户。 感谢回复。 - DI_one

0

有几种方法可以使用Espresso Intents进行测试https://google.github.io/android-testing-support-library/docs/espresso/intents/

您可以使用intended()语法验证是否发送了Intent以打开帐户选择器。 您还可以使用intending().respondWith()语法验证选择器返回结果的活动行为。

如果您真的想直接与选择器交互,您可以尝试使用UIAutomator API:https://developer.android.com/topic/libraries/testing-support-library/index.html#UIAutomator

UIAutomator可在Espresso测试中使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接