如何为浓缩咖啡测试禁用 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) 来自动填充。
当发生以下情况之一时,上下文结束:
- commit() 被调用或所有可保存的视图都消失了。
- 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);
在您的设备中,转到这条路线
设置 > 系统 > 语言和输入 > 高级 > 自动填充服务并取消它
运行 使用 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 classdefaultConfig {
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) 来自动填充。
当发生以下情况之一时,上下文结束:
- commit() 被调用或所有可保存的视图都消失了。
- 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);
在您的设备中,转到这条路线 设置 > 系统 > 语言和输入 > 高级 > 自动填充服务并取消它