如何为浓缩咖啡测试禁用 Android Oreo 的新自动填充功能

How to disable the new Autofill feature from Android Oreo for espresso tests

运行 使用 sdk 26 在 android 设备上进行的测试导致它们失败,因为新的 Autofill 功能会在 espresso 试图点击它们时隐藏这些字段。

我 运行 我在 firebase 测试实验室进行测试,所以我无法在我的测试设备上手动禁用它们。

部分图片:

1。单击用户名字段前密码可见。

2。单击用户名字段后,此自动填充对话框会隐藏密码字段:

3。登录后显示另一个填充对话框:

Espresso 现在无法点击密码字段,因为自动填充对话框隐藏了我的字段并且 fail

使用AutofillManager#disableAutofillServices() 仅禁用#2。对话框但#3。还在。

如何在测试设备上禁用自动填充?

根据文档,您可以使用 AutofillManager#disableAutofillServices() API:

禁用自动填充服务

If the app calling this API has enabled autofill services they will be disabled.

用法:


    val autofillManager: AutofillManager = context.getSystemService(AutofillManager::class.java)
    autofillManager.disableAutofillServices()

您可以在测试的 @Before 步中执行此操作。

测试时禁用自动填充。在 gradle

中定义一个 TestRunner class
defaultConfig {
    testInstrumentationRunner "com.cover.android.TestRunner"
}

然后

public class TestRunner extends AndroidJUnitRunner {

  @Override
  public void onCreate(Bundle arguments) {
      super.onCreate(arguments);
      CustomEditText.TESTING = TRUE;
  }
}

然后使用自定义版本的 EditText

public class CustomEditText extends AppCompatEditText {
public static boolean TESTING = false;
public CustomEditText(Context context) {
    super(context);
}

@Override
public int getAutofillType() {
    return TESTING? AUTOFILL_TYPE_NONE : super.getAutofillType();
}

根据文档: 当视图聚焦于数据集并且是数据集的一部分时。当通过 registerCallback(AutofillCallback) 注册一个 AutofillManager.AutofillCallback 显示可供性时,可以通知应用程序。当用户从可供性中选择数据集时,数据集中存在的所有视图都会通过调用自动填充 (AutofillValue) 或自动填充 (SparseArray) 来自动填充。

当发生以下情况之一时,上下文结束:

  1. commit() 被调用或所有可保存的视图都消失了。
  2. cancel() 被调用。

从任何线程调用它的方法都是安全的。

必须使用带有参数 AutofillManager.class.

的 Context.getSystemService(Class) 来获得此 class 的实例

使用 : disableAutofillServices() 方法禁用服务。

adb shell pm disable com.google.android.gms/com.google.android.gms.autofill.service.AutofillService

这应该会禁用自动填充服务。与手动关闭系统设置中的自动填充服务相同。它至少在模拟器上有效。但这需要root权限。

禁用自动填充服务的另一种方法是更改​​ autofill_service 设置。

adb shell settings put secure autofill_service null

我很幸运在 Espresso 测试期间禁用了自动填充功能,只要输入文本就会应用自定义 ViewActions。

            .onView(...)
            .perform(
                    new ViewAction() {
                        @Override
                        public Matcher<View> getConstraints() {
                            return Matchers.any(View.class);
                        }

                        @Override
                        public String getDescription() {
                            return "Marking view not important for autofill";
                        }

                        @Override
                        public void perform(UiController uiController, View view) {
                            // Required to disable autofill suggestions during tests on API 26+
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                view.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
                            }
                        }
                    })
            .perform(click())
            .perform(clearText())
            .perform(typeText(textToType))
            .perform(
                    new ViewAction() {
                        @Override
                        public Matcher<View> getConstraints() {
                            return Matchers.any(View.class);
                        }

                        @Override
                        public String getDescription() {
                            return "Dismissing autofill picker";
                        }

                        @Override
                        public void perform(UiController uiController, View view) {
                            // Required to dismiss the autofill picker during tests on API 26+
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                AutofillManager autofillManager =
                                        view.getContext()
                                                .getSystemService(AutofillManager.class);
                                if (autofillManager != null) autofillManager.cancel();
                            }
                        }
                    });

基于@Alan K 解决方案的替代代码组织。

创建 class DisableAutofillAction:

public class DisableAutofillAction implements ViewAction {

    @Override
    public Matcher<View> getConstraints() {
        return Matchers.any(View.class);
    }

    @Override
    public String getDescription() {
        return "Dismissing autofill picker";
    }

    @Override
    public void perform(UiController uiController, View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            AutofillManager autofillManager = view.getContext().getSystemService(AutofillManager.class);

            if (autofillManager != null) {
                autofillManager.cancel();
            }
        }
    }
}

并且,当您需要为 editTextPassword 禁用自动填充时,在您的代码中...

editTextPassword.perform(..., ViewActions.closeSoftKeyboard(), DisableAutofillAction())

以下代码片段可用于忽略新的 android 建议:

getWindow().getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);

在您的设备中,转到这条路线 设置 > 系统 > 语言和输入 > 高级 > 自动填充服务并取消它