如何将失败测试截图嵌入Android Espresso自动生成的HTML报告?
嘿,这个问题太有共鸣了——手动从设备里抠截图真的是测试流程里的一大痛点!我来分享几个亲测有效的方案,帮你把截图自动嵌入Espresso的HTML报告里,不用再折腾文件提取:
方案1:用AndroidX Test的截图API+自定义TestRule(官方推荐)
Espresso本身没直接内置截图嵌入报告的功能,但AndroidX Test库提供了适配Espresso的截图工具,结合自定义TestWatcher规则,可以在测试失败时自动截图并保存到本地电脑的测试报告目录(而非设备存储),完美解决提取麻烦的问题。
这里给你一段可直接复用的代码示例:
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.rules.TestWatcher import org.junit.runner.Description import java.io.IOException import androidx.test.core.graphics.captureToBitmap import androidx.test.core.graphics.writeToTestStorage @RunWith(AndroidJUnit4::class) class SampleFailureScreenshotTest { // 自定义TestWatcher,监听测试失败事件 @get:Rule val failureScreenshotRule = object : TestWatcher() { override fun failed(e: Throwable?, description: Description?) { super.failed(e, description) // 捕获当前屏幕的Bitmap val screenBitmap = onView(isRoot()).captureToBitmap() // 用测试方法名命名截图,方便对应到测试用例 val screenshotFileName = "${description?.methodName}_failed.png" try { // 自动保存到本地测试报告目录:build/outputs/androidTest-results/connected/ screenBitmap.writeToTestStorage(screenshotFileName) } catch (ioe: IOException) { e?.printStackTrace() ioe.printStackTrace() } } } @Test fun testScenarioThatMayFail() { // 你的Espresso测试代码,比如: // onView(withId(R.id.some_button)).perform(click()) // onView(withText("Expected Text")).check(matches(isDisplayed())) } }
这段代码的核心是captureToBitmap()和writeToTestStorage()——前者是AndroidX Test提供的Espresso视图截图方法,后者会自动把截图存到和Espresso HTML报告同目录的位置,之后你可以在报告里直接引用这些截图(如果需要自动嵌入,还可以结合Gradle插件生成带截图的增强报告)。
方案2:用第三方测试报告插件(省心省力)
如果不想自己写规则,直接用成熟的第三方插件更省心,比如Allure for Android或者Espresso Report Generator:
- 这类插件会自动监听测试失败事件,触发截图并嵌入生成的HTML报告
- 只需要添加少量依赖和配置,就能实现“失败即截图+报告自动关联”的全流程
比如Allure的配置,只需要在build.gradle里添加依赖,然后在测试失败时调用Allure.addAttachment()方法,生成的报告就会自动展示截图。
方案3:改进UiAutomator代码,自动拉取截图到本地
如果你还是想继续用UiAutomator的截图逻辑,可以在测试完成后自动通过adb把设备里的截图拉到本地报告目录,避免手动操作:
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.android.uiautomator.core.UiDevice import org.junit.After import org.junit.Test import org.junit.runner.RunWith import java.io.File @RunWith(AndroidJUnit4::class) class UiAutomatorScreenshotTest { private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @After fun pullScreenshotOnFailure() { // 这里可以结合TestWatcher判断测试是否失败,再执行拉取 val screenshotFile = device.takeScreenshot(File("/sdcard/test_screenshot.png")) // 通过adb命令自动拉取到本地报告目录 Runtime.getRuntime().exec("adb pull /sdcard/test_screenshot.png ./build/outputs/androidTest-results/connected/screenshots/") } @Test fun testWithUiAutomator() { // 你的UiAutomator测试代码 } }
不过这个方法依赖adb环境,不如方案1直接存本地来得高效。
关于Espresso内置功能的说明
Espresso本身确实没有直接把截图嵌入HTML报告的内置功能,但AndroidX Test库提供的截图API是官方适配Espresso的,比UiAutomator更贴合Espresso的测试流程,也是目前最推荐的方案。
内容的提问来源于stack exchange,提问作者Zeek Aran

