如何编写模拟 GPS 位置的 Espresso 测试并在 Google Testlab 中使用它们?
How to write Espresso Tests which are mocking GPS locations and use them in Google Testlab?
我用 Espresso Recorder 录制了一份浓缩咖啡测试。我想在我的应用中测试一些位置变化。
目前我正在使用此代码模拟位置:
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy( Criteria.ACCURACY_FINE );
String mocLocationProvider = LocationManager.GPS_PROVIDER;//lm.getBestProvider( criteria, true );
lm.addTestProvider(mocLocationProvider, false, false,
false, false, true, true, true, 0, 5);
lm.setTestProviderEnabled(mocLocationProvider, true);
Location loc = new Location(mocLocationProvider);
Location mockLocation = new Location(mocLocationProvider); // a string
mockLocation.setLatitude(-26.902038); // double
mockLocation.setLongitude(-48.671337);
mockLocation.setAltitude(loc.getAltitude());
mockLocation.setTime(System.currentTimeMillis());
mockLocation.setAccuracy(1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
lm.setTestProviderLocation( mocLocationProvider, mockLocation);
我还添加了调试清单文件的权限:
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
但不幸的是我仍然遇到安全异常:
java.lang.SecurityException: mypackage.test from uid not allowed to perform MOCK_LOCATION
我想 运行 在 Google Firebase 测试实验室中使用模拟位置记录的测试用例。我该如何解决这个问题?
基本上您必须在开发者选项中启用该应用程序(select 模拟位置应用程序)。由于无法控制google平台上的设备,必须使用ADB命令才能启用。
appops set {yourPackageName} android:mock_location allow
例如,这就是我在 @before 函数中为模拟位置测试所做的事情:
@Before
fun grantPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
with(getInstrumentation().uiAutomation) {
...
executeShellCommand("appops set " + InstrumentationRegistry.getTargetContext().packageName + " android:mock_location allow")
Thread.sleep(1000)
...
}
}
}
根据这种方法,请注意,您还可以为 gradle 任务创建一个片段,以便在您插入任何新设备时自动在您的工作站上执行该任务。参见示例:
希望对您有所帮助!
MrAurelien 提出了一个很好的解决方案。但最好以不同的方式实现它。
Thread.sleep(1000)
使您的测试变慢且不稳定。这是一个工作稳定的不同版本。
@Before
fun grantPermission() {
instrumentation.uiAutomation.executeShellCommandBlocking(
"appops set ${appContext.packageName} android:mock_location allow"
)
}
executeShellCommandBlocking
是一个自定义实用程序函数,它等待 appops 命令完成。
fun UiAutomation.executeShellCommandBlocking(command: String) {
val output = executeShellCommand(command)
FileInputStream(output.fileDescriptor).use { it.readBytes() }
}
中使用了这个解决方案
我用 Espresso Recorder 录制了一份浓缩咖啡测试。我想在我的应用中测试一些位置变化。
目前我正在使用此代码模拟位置:
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy( Criteria.ACCURACY_FINE );
String mocLocationProvider = LocationManager.GPS_PROVIDER;//lm.getBestProvider( criteria, true );
lm.addTestProvider(mocLocationProvider, false, false,
false, false, true, true, true, 0, 5);
lm.setTestProviderEnabled(mocLocationProvider, true);
Location loc = new Location(mocLocationProvider);
Location mockLocation = new Location(mocLocationProvider); // a string
mockLocation.setLatitude(-26.902038); // double
mockLocation.setLongitude(-48.671337);
mockLocation.setAltitude(loc.getAltitude());
mockLocation.setTime(System.currentTimeMillis());
mockLocation.setAccuracy(1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
lm.setTestProviderLocation( mocLocationProvider, mockLocation);
我还添加了调试清单文件的权限:
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
但不幸的是我仍然遇到安全异常:
java.lang.SecurityException: mypackage.test from uid not allowed to perform MOCK_LOCATION
我想 运行 在 Google Firebase 测试实验室中使用模拟位置记录的测试用例。我该如何解决这个问题?
基本上您必须在开发者选项中启用该应用程序(select 模拟位置应用程序)。由于无法控制google平台上的设备,必须使用ADB命令才能启用。
appops set {yourPackageName} android:mock_location allow
例如,这就是我在 @before 函数中为模拟位置测试所做的事情:
@Before
fun grantPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
with(getInstrumentation().uiAutomation) {
...
executeShellCommand("appops set " + InstrumentationRegistry.getTargetContext().packageName + " android:mock_location allow")
Thread.sleep(1000)
...
}
}
}
根据这种方法,请注意,您还可以为 gradle 任务创建一个片段,以便在您插入任何新设备时自动在您的工作站上执行该任务。参见示例:
希望对您有所帮助!
MrAurelien 提出了一个很好的解决方案。但最好以不同的方式实现它。
Thread.sleep(1000)
使您的测试变慢且不稳定。这是一个工作稳定的不同版本。
@Before
fun grantPermission() {
instrumentation.uiAutomation.executeShellCommandBlocking(
"appops set ${appContext.packageName} android:mock_location allow"
)
}
executeShellCommandBlocking
是一个自定义实用程序函数,它等待 appops 命令完成。
fun UiAutomation.executeShellCommandBlocking(command: String) {
val output = executeShellCommand(command)
FileInputStream(output.fileDescriptor).use { it.readBytes() }
}
中使用了这个解决方案