我需要使用Espresso测试项目自动化以下操作的UI测试。
操作:
点击一个按钮,打开我的手机相机。 拍照并将图像保存在SD卡存储中。 完成后还要更新屏幕上的小图像视图。
应用程序运行良好,但对于所有其他操作和类似上述操作的操作,手动测试变成了一个耗时的过程。
我需要使用Espresso测试项目自动化以下操作的UI测试。
操作:
点击一个按钮,打开我的手机相机。 拍照并将图像保存在SD卡存储中。 完成后还要更新屏幕上的小图像视图。
应用程序运行良好,但对于所有其他操作和类似上述操作的操作,手动测试变成了一个耗时的过程。
我遇到了类似的问题,发现以下链接提供了最佳可用解决方案:相机UI测试
// CameraActivityInstrumentationTest.java
public class CameraActivityInstrumentationTest {
// IntentsTestRule is an extension of ActivityTestRule. IntentsTestRule sets up Espresso-Intents
// before each Test is executed to allow stubbing and validation of intents.
@Rule
public IntentsTestRule<CameraActivity> intentsRule = new IntentsTestRule<>(CameraActivity.class);
@Test
public void validateCameraScenario() {
// Create a bitmap we can use for our simulated camera image
Bitmap icon = BitmapFactory.decodeResource(
InstrumentationRegistry.getTargetContext().getResources(),
R.mipmap.ic_launcher);
// Build a result to return from the Camera app
Intent resultData = new Intent();
resultData.putExtra("data", icon);
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
// Stub out the Camera. When an intent is sent to the Camera, this tells Espresso to respond
// with the ActivityResult we just created
intending(toPackage("com.android.camera2")).respondWith(result);
// Now that we have the stub in place, click on the button in our app that launches into the Camera
onView(withId(R.id.btnTakePicture)).perform(click());
// We can also validate that an intent resolving to the "camera" activity has been sent out by our app
intended(toPackage("com.android.camera2"));
// ... additional test steps and validation ...
}
}
对我来说,所有的解决方案都无法直接使用,但以下方法可以。这是这个答案和这个评论的结合。
如果不调用Intents.init()
,我的测试将会失败,并出现以下异常:
java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.test.espresso.intent.OngoingStubbing androidx.test.espresso.intent.Intents.internalIntending(org.hamcrest.Matcher)' on a null object reference
完整解决方案:
@Before
fun setUp() {
Intents.init()
}
@After
fun tearDown() {
Intents.release()
}
@Test
fun testCameraIntent() {
// Build an ActivityResult that will return from the camera app and set your extras (if any).
val resultData = Intent()
resultData.putExtra(MediaStore.EXTRA_OUTPUT, "test.file.url")
val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
// Mock the camera response. Now whenever an intent is sent to the camera, Espresso will respond with the result we pass here.
intending(hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result)
// Now click on the button in your app that launches the camera.
onView(withId(R.id.button_camera)).perform(click());
// Optionally, we can also verify that the intent to the camera has actually been sent from out.
intended(hasAction(MediaStore.ACTION_IMAGE_CAPTURE))
// At this point the onActivityResult() has been called so verify that whatever view is supposed to be displayed is indeed displayed.
onView(withId(R.id.some_view)).check(matches(isDisplayed()))
}
@Rule
public IntentsTestRule<ImageViewerActivity> mIntentsRule = new IntentsTestRule<>(
ImageViewerActivity.class);
@Before
public void stubCameraIntent() {
ActivityResult result = createImageCaptureActivityResultStub();
// Stub the Intent.
intending(hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result);
}
@Test
public void takePhoto_drawableIsApplied() {
// Check that the ImageView doesn't have a drawable applied.
onView(withId(R.id.imageView)).check(matches(not(hasDrawable())));
// Click on the button that will trigger the stubbed intent.
onView(withId(R.id.button_take_photo)).perform(click());
// With no user interaction, the ImageView will have a drawable.
onView(withId(R.id.imageView)).check(matches(hasDrawable()));
}
private ActivityResult createImageCaptureActivityResultStub() {
// Put the drawable in a bundle.
Bundle bundle = new Bundle();
bundle.putParcelable(ImageViewerActivity.KEY_IMAGE_DATA, BitmapFactory.decodeResource(
mIntentsRule.getActivity().getResources(), R.drawable.ic_launcher));
// Create the Intent that will include the bundle.
Intent resultData = new Intent();
resultData.putExtras(bundle);
// Create the ActivityResult with the Intent.
return new ActivityResult(Activity.RESULT_OK, resultData);
}
查看此链接以获取更多详细信息IntentsAdvancedsample