3. CTS Camera Test框架:Test Harness、CameraTestRule、CameraUtil工具类
CTS Camera 测试框架是连接测试用例与 Android Camera HAL 实现的桥梁。理解其核心组件——Test Harness、CameraTestRule 和 CameraUtil——是编写高效、可维护的 Camera CTS 用例的基础。本章将深入剖析这三个组件的职责、交互方式及典型使用模式。
3.1 框架总体架构
CTS Camera 测试框架采用分层设计,将测试逻辑、设备交互与结果验证解耦。下图展示了测试用例执行时各组件间的协作关系:
关键设计原则:Test Harness 作为测试执行引擎,CameraTestRule 作为测试生命周期管理器,CameraUtil 作为底层 Camera API 的封装层。三者各司其职,共同构建了可扩展、可复用的测试框架。
3.2 Test Harness:测试执行引擎
Test Harness 是 CTS Camera 测试框架的核心调度组件,负责测试用例的加载、参数化配置、执行与结果收集。它运行在 Android 测试基础设施之上,与 Trade Federation (TF) 深度集成。
3.2.1 核心职责
- 测试用例发现与加载:扫描指定测试类,识别带有
@Test注解的方法。 - 参数化配置:解析
@ParameterizedTest或自定义注解,为每个测试方法注入不同的 Camera ID、分辨率、格式等参数组合。 - 资源管理:协调 Camera 硬件资源的分配与释放,避免并发冲突。
- 结果收集:捕获测试过程中的日志、性能指标、错误信息,生成结构化测试报告。
3.2.2 典型配置示例
在 CTS 测试配置 XML 文件中,Test Harness 通过以下方式定义:
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="android.hardware.camera2.cts" />
<option name="runner" value="androidx.test.runner.AndroidJUnit4" />
<option name="instrumentation-arg" key="camera_ids" value="0,1" />
<option name="instrumentation-arg" key="test_timeout_ms" value="30000" />
</test>
实践建议:在调试特定 HAL 行为时,可通过
instrumentation-arg 动态调整 Test Harness 的参数,例如只测试后置 Camera 或特定分辨率,以缩短测试迭代周期。
3.3 CameraTestRule:测试生命周期管理器
CameraTestRule 是 JUnit 的 TestRule 实现,它封装了 Camera 测试的通用生命周期逻辑,包括 Camera 的打开、关闭、异常处理以及资源清理。测试用例通过 @Rule 注解声明 CameraTestRule 实例,从而自动获得这些能力。
3.3.1 生命周期钩子
| 钩子方法 | 触发时机 | 典型用途 |
|---|---|---|
before() |
每个测试方法执行前 | 初始化 CameraManager、获取 Camera ID 列表、创建 CameraDevice |
after() |
每个测试方法执行后 | 关闭 CameraDevice、释放 CaptureSession、清理资源 |
onFailed() |
测试方法抛出异常时 | 捕获异常上下文、保存关键日志、标记测试失败原因 |
onSkipped() |
测试方法被跳过时 | 记录跳过原因(如硬件不支持、权限不足) |
3.3.2 使用示例
public class CameraPreviewTest {
@Rule
public CameraTestRule mCameraRule = new CameraTestRule();
@Test
public void testPreviewStability() throws Exception {
// CameraTestRule 已自动打开 Camera
CameraDevice camera = mCameraRule.getCameraDevice();
assertNotNull("CameraDevice should not be null", camera);
// 创建预览请求
CaptureRequest.Builder previewBuilder =
camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// ... 配置 Surface 并开始预览
// 测试结束后,CameraTestRule 自动关闭 Camera
}
}
注意事项:CameraTestRule 默认使用 Camera ID 0。如果测试需要操作多个 Camera 或特定 ID,必须在
@Test 注解或 Test Harness 配置中显式指定。忽略此点可能导致测试在双摄设备上误用错误的 Camera 单元。
3.4 CameraUtil:底层 Camera API 封装
CameraUtil 是 CTS Camera 测试框架中的工具类集合,它封装了 Android Camera2 API 的复杂调用逻辑,为测试用例提供简洁、稳定的接口。CameraUtil 的核心目标是减少测试代码中的样板代码,并统一错误处理策略。
3.4.1 核心功能模块
- Camera 打开与关闭:封装
CameraManager.openCamera()的异步回调,提供同步等待机制。 - Session 管理:简化
CameraDevice.createCaptureSession()的配置流程,支持输出配置列表的快速构建。 - 请求构造:提供
createCaptureRequest()的便捷方法,自动填充默认模板参数。 - 特性查询:封装
CameraCharacteristics的读取逻辑,提供类型安全的查询接口。
3.4.2 关键工具方法
| 方法签名 | 功能描述 | 返回类型 |
|---|---|---|
openCamera(String cameraId) |
同步打开指定 Camera,超时默认 5 秒 | CameraDevice |
createCaptureSession(CameraDevice, List<Surface>) |
基于输出 Surface 列表创建 CaptureSession | CameraCaptureSession |
getCharacteristics(String cameraId) |
获取 Camera 特性集合 | CameraCharacteristics |
isFeatureSupported(String cameraId, Key<?> key) |
检查指定 Camera 是否支持某特性 | boolean |
waitForIdle(CameraCaptureSession) |
等待 Session 进入空闲状态 | void |
3.4.3 典型使用模式
public class CameraUtilDemoTest {
@Rule
public CameraTestRule mCameraRule = new CameraTestRule();
@Test
public void testCameraOpenAndCharacteristics() throws Exception {
// 使用 CameraUtil 打开 Camera
CameraDevice camera = CameraUtil.openCamera("0");
assertNotNull("Camera should be opened", camera);
// 查询 Camera 特性
CameraCharacteristics chars = CameraUtil.getCharacteristics("0");
Integer[] availableFpsRanges = chars.get(
CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
assertNotNull("FPS ranges should not be null", availableFpsRanges);
// 检查是否支持 HDR+
boolean hdrSupported = CameraUtil.isFeatureSupported("0",
CameraCharacteristics.CONTROL_AE_MODE_AVAILABLE_HDR);
assertTrue("HDR+ should be supported", hdrSupported);
// 关闭 Camera
CameraUtil.closeCamera(camera);
}
}
最佳实践:在编写 CTS 测试用例时,优先使用 CameraUtil 提供的方法,而不是直接调用 Camera2 API。这不仅能减少代码量,还能确保错误处理逻辑与 CTS 框架保持一致,避免因底层 API 调用方式差异导致的测试不稳定。
3.5 组件交互流程
以下 SVG 图展示了从测试用例启动到 HAL 调用的完整交互流程:
3.6 常见问题与避坑指南
| 问题场景 | 根因分析 | 解决方案 |
|---|---|---|
| CameraTestRule 未正确初始化 | @Rule 注解未使用 public 字段,或 Test Harness 未正确加载 | 确保 @Rule 字段为 public 且非 static;检查测试配置 XML 中的 runner 配置 |
| CameraUtil.openCamera() 超时 | HAL 层 open() 实现耗时过长,或 Camera 被其他进程占用 | 增加超时时间(通过 Test Harness 参数);检查设备上其他 Camera 应用是否已关闭 |
| Session 创建失败 | 输出 Surface 配置与 HAL 支持的流格式不匹配 | 使用 CameraUtil.getCharacteristics() 查询支持的输出配置,确保 Surface 格式、尺寸在支持列表中 |
| 测试结果不稳定(Flaky) | 资源未正确释放,导致后续测试受前序测试状态影响 | 检查 CameraTestRule 的 after() 方法是否完整释放所有资源;使用 @Before 重置全局状态 |
重要提醒:在 CTS 测试中,CameraTestRule 和 CameraUtil 的版本必须与 Android 平台版本匹配。使用不匹配的版本可能导致 API 行为差异,进而产生误报或漏报。建议在构建测试时,通过 Gradle 依赖管理锁定框架版本。
3.7 小结
本章详细介绍了 CTS Camera Test 框架的三个核心组件:
- Test Harness 作为测试执行引擎,负责参数化配置与结果收集。
- CameraTestRule 作为生命周期管理器,自动化 Camera 资源的打开与关闭。
- CameraUtil 作为底层 API 封装,简化 Camera2 API 的调用复杂度。