【问题标题】:Reset app state between InstrumentationTestCase runs在 InstrumentationTestCase 运行之间重置应用状态
【发布时间】:2016-06-02 16:14:01
【问题描述】:

我的一位 QA 工程师正在支持一个具有相当大的代码库和许多不同 SharedPreferences 文件的应用程序。前几天他来找我询问如何在测试运行之间重置应用程序状态,就好像它已被卸载 - 重新安装一样。

Espresso(他正在使用)和原生的 Android 测试框架似乎都不支持该功能,所以我不知道该告诉他什么。使用本机方法来清除所有不同的 SharedPreferences 文件将是一个非常脆弱的解决方案。

如何在检测期间重置应用程序状态?

【问题讨论】:

标签: android-testing android-espresso android-instrumentation


【解决方案1】:

当前的 espresso 不提供任何重置应用程序状态的机制。但是对于每个方面(pref、db、files、permissions)都有一个解决方案。

最初,您必须避免 espresso 自动启动您的活动,以便您有足够的时间进行重置。

@Rule
public ActivityTestRule<Activity> activityTestRule = new ActivityTestRule<>(Activity.class, false, false);

然后用

开始你的活动
activityTestRule.launchActivity(null)

要重置首选项,您可以使用以下 sn-p(在开始活动之前)

File root = InstrumentationRegistry.getTargetContext().getFilesDir().getParentFile();
String[] sharedPreferencesFileNames = new File(root, "shared_prefs").list();
for (String fileName : sharedPreferencesFileNames) {
    InstrumentationRegistry.getTargetContext().getSharedPreferences(fileName.replace(".xml", ""), Context.MODE_PRIVATE).edit().clear().commit();
}

您也可以在开始活动后重置偏好设置。但随后活动可能已经阅读了偏好。

您的应用程序类只启动一次,并且在您可以重置首选项之前已经启动。

我已经开始编写一个库,它应该可以让 espresso 和 uiautomator 的测试更加简单。这包括用于重置应用程序数据的工具。 https://github.com/nenick/espresso-macchiato 参见例如 EspAppDataTool 以及清除首选项、数据库、缓存文件和存储文件的方法。

【讨论】:

  • 该项目使用了很多不同的 SharedPreferences 文件。就像我说的那样,使用本机方法来清除所有不同的 SharedPreferences 文件将是一个非常脆弱的解决方案。 :(
  • 如果你有一个或 9999 tausend SharedPreferences,它是相等的。通常它们都位于 shared_prefs 中。你还有什么期待?作为替代方案,您可以编写一个脚本来单独运行每个测试,在每个测试之间使用 adb 清除应用程序数据,然后开始下一个测试。
  • 哦!我看到你在那里做了什么。我读得太快了,认为“shared_prefs”是 your_pref_file_name_here 的简写,但这实际上是 SharedPreferences 文件的根文件夹。
  • 你不能用Instrumentation.getTargetContext().deleteSharedPreferences(...)吗?
【解决方案2】:

改进@nenick 的解决方案,将状态清除行为封装在自定义ActivityTestRule 中。如果您这样做,您可以允许测试继续自动启动活动,而无需您干预。使用自定义ActivityTestRule,活动在启动测试时已经处于所需状态。

规则特别有用,因为它们不依赖于任何特定的测试类,因此可以在任何测试类或任何项目中轻松重用。

以下是我为确保在每次测试启动 Activity 时退出应用而实施的一种方法。一些测试在失败时会使应用程序处于登录状态。这会导致后面的测试也失败,因为后面的测试假设他们需要登录,但应用程序已经登录了。

public class SignedOutActivityTestRule<T extends Activity> extends ActivityTestRule<T> {

    public SignedOutActivityTestRule(Class<T> activityClass) {
        super(activityClass);
    }

    @Override
    protected void beforeActivityLaunched() {
        super.beforeActivityLaunched();
        InstrumentationRegistry.getTargetContext()
                .getSharedPreferences(
                        Authentication.SHARED_PREFERENCES_NAME,
                        Context.MODE_PRIVATE)
                .edit()
                .remove(Authentication.KEY_SECRET)
                .remove(Authentication.KEY_USER_ID)
                .apply();
    }

}

【讨论】:

    【解决方案3】:

    您可以尝试将其添加到 gradle:

    android {
    ...
    defaultConfig {
    ...
        testInstrumentationRunnerArguments clearPackageData: 'true'
       }
    }
    

    参考https://developer.android.com/training/testing/junit-runner

    要在每次测试后从设备的 CPU 和内存中删除所有共享状态,请使用 clearPackageData 标志。

    【讨论】:

      猜你喜欢
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      • 2017-01-18
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      相关资源
      最近更新 更多