【发布时间】:2011-07-21 13:18:34
【问题描述】:
是否对应用程序进行运行时检查,以确定它是否作为仪器测试的一部分运行?
背景:我们的应用程序在启动时执行数据库同步。但这只有在定期启动时才会发生。它尤其会干扰测试数据库同步的仪器测试。不足为奇。
对于所有其他测试,这只是在浪费 CPU 周期。
【问题讨论】:
-
你找到解决办法了吗?
标签: android unit-testing instrumentation
是否对应用程序进行运行时检查,以确定它是否作为仪器测试的一部分运行?
背景:我们的应用程序在启动时执行数据库同步。但这只有在定期启动时才会发生。它尤其会干扰测试数据库同步的仪器测试。不足为奇。
对于所有其他测试,这只是在浪费 CPU 周期。
【问题讨论】:
标签: android unit-testing instrumentation
一个更简单的解决方案是检查仅存在于测试类路径中的类,与 JUnit 4 一起使用(与使用 ActivityUnitTestCase 的解决方案不同)并且不需要向您的活动/服务发送自定义意图(这可能在某些情况下甚至不可能)
private boolean isTesting() {
try {
Class.forName("com.company.SomeTestClass");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
【讨论】:
从 API 级别 11 开始,ActivityManager.isRunningInTestHarness() 方法可用。这可能会做你想做的事。
【讨论】:
如果您使用的是 Robolectric,您可以执行以下操作:
public boolean isUnitTest() {
String device = Build.DEVICE;
String product = Build.PRODUCT;
if (device == null) {
device = "";
}
if (product == null) {
product = "";
}
return device.equals("robolectric") && product.equals("robolectric");
}
【讨论】:
如果您使用的是 ActivityUnitTestCase,您可以使用 setApplication 设置自定义应用程序对象,并在其中设置一个标志来打开或关闭数据库同步?在我的博客上有一个使用自定义 Application 对象的示例:
http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-3/
【讨论】:
setApplication 方法,而简单的 AndroidTestCase 不会。但无论如何,它们似乎运行良好。反正它似乎是唯一的开放。谢谢。
您可以将额外的意图传递给您的活动,表明它正在测试中。
1) 在您的测试中,将“testMode”额外传递给您的活动:
public void setUp() throws Exception {
super.setUp();
Intent activityIntent = new Intent();
activityIntent.putExtra("testMode", true);
setActivityIntent(activityIntent);
}
2) 在您的活动中,检查 testMode:
Bundle extras = getIntent().getExtras();
if (extras != null && extras.getBoolean("testMode")) {
// disable your database sync
}
【讨论】:
d= (◕‿↼ ) Great answer,但如果某些库开发者(如我)想知道主机(或使用库的应用)是否正在测试,请尝试:
import android.content.pm.ApplicationInfo;
// ...
private static int wasTestRun = 0xDEAD;
/**
* Should only be used to speed up testing (no behavior change).
* @return true in tests, if Gradle has the right dependencies.
*/
public static boolean isTestRun(@NonNull Context context) {
if (wasTestRun != 0xDEAD) {
return wasTestRun != 0;
}
// Ignore release builds (as App may be using JUnit by mistake).
if (isDebuggable(context)) {
try {
Class.forName("org.junit.runner.Runner");
wasTestRun = 1;
return true;
} catch (ClassNotFoundException ignored) {
}
}
wasTestRun = 0;
return false;
}
public static boolean isDebuggable(@Nullable Context context) {
return context != null && (context.getApplicationContext()
.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
请注意,我没有使用任何
AtomicBoolean或其他助手,因为它已经非常快了(锁定可能只会降低速度)。
【讨论】:
这对我有用,因为没有实际设备正在运行
public static boolean isUnitTest() {
return Build.BRAND.startsWith(Build.UNKNOWN) && Build.DEVICE.startsWith(Build.UNKNOWN) && Build.DEVICE.startsWith(Build.UNKNOWN) && Build.PRODUCT.startsWith(Build.UNKNOWN);
}
【讨论】:
你可以试试这个
if (isRunningTest == null) {
isRunningTest = false;
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
List<StackTraceElement> list = Arrays.asList(stackTrace);
for (StackTraceElement element : list) {
if (element.getClassName().startsWith("androidx.test.runner.MonitoringInstrumentation")) {
isRunningTest = true;
break;
}
}
}
【讨论】: