【问题标题】:Camera Operation UI testing with Espresso使用 Espresso 进行相机操作 UI 测试
【发布时间】:2015-01-19 07:20:02
【问题描述】:

我需要自动化我的 UI 测试,以便使用 espresso 测试项目进行以下操作。

操作:

单击打开我的手机摄像头的按钮。捕获图像,并将图像保存在 sdcard 存储中。完成后还会在屏幕上更新一个小图像视图。

应用程序运行良好,但对于所有其他操作和上述类似类型的操作,一次又一次地手动测试它成为一个耗时的过程。

【问题讨论】:

标签: android unit-testing integration-testing android-testing android-espresso


【解决方案1】:

我正在处理类似的问题 并在以下链接中找到最佳可用解决方案 Camera UI test

// 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 ...
    }
}

【讨论】:

  • 某些设备,如 SAMSUNG Galaxy S8,其相机应用程序的包名称为“com.sec.android.app.camera”。这个解决方案在那个设备上不起作用是吗?
【解决方案2】:

如果您仍有需要,可以使用模拟活动结果的新 Espresso-Intent 来测试此流程。 See the sample from Android Testing

【讨论】:

【解决方案3】:

Google 提供了一个关于此相机问题的示例,他们展示了如何存根相机意图、启动相机以及测试图像是否来自存根意图,并显示在 imageView 上。

@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

【讨论】:

    【解决方案4】:

    对我来说,没有一个解决方案是开箱即用的,但以下解决方案可以。它是this answerthis comment 的组合。

    如果不调用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()))        
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      相关资源
      最近更新 更多