4. CTS测试结果解读

CTS测试执行完成后,生成的结果报告是故障排查的核心入口。正确解读报告结构、理解测试状态含义、快速定位日志文件,是每一位Android兼容性认证工程师必须掌握的基础技能。本节将系统拆解CTS报告的组织方式与关键要素。

4.1 报告结构概览

CTS测试结果以XML格式存储在 android-cts/repository/results/ 目录下,每次执行生成一个以时间戳命名的子目录(如 2025-03-21_14-30-00)。该目录包含以下核心文件:

文件/目录 说明 故障排查优先级
test_result.xml 主结果文件,包含所有模块的测试摘要与详细结果 最高
test_result.css 结果页面的样式表,浏览器打开时自动加载 低
logs/ 存放设备日志(logcat)、测试用例日志、崩溃dump 最高
test_result.html 基于XML生成的可视化HTML报告,便于快速浏览 高
crashes/ 测试过程中发生的native crash或anr记录 高
排查起点: 优先打开 test_result.html 查看整体通过率,再对照 test_result.xml 定位具体失败的测试项。日志文件集中在 logs/ 目录下,按模块和测试用例组织。
CTS测试报告目录结构 CTS测试报告目录结构 results/ 2025-03-21_14-30-00/ test_result.xml test_result.html test_result.css logs/ crashes/ 说明: • test_result.xml 是机器可读的完整结果,test_result.html 是可视化摘要。 • logs/ 目录按模块和测试用例组织,是定位失败原因的主要数据源。

4.2 测试状态含义:Pass / Fail / NotExecuted

CTS报告中每个测试用例(Test Case)都有明确的状态标记。理解这些状态是判断问题归属的前提:

状态 含义 典型原因 排查方向
Pass 测试用例完全通过,未触发任何断言失败或异常 — 无需处理
Fail 测试用例执行完毕,但至少一个断言条件未满足 API行为不符合规范、权限缺失、返回值错误 检查日志中的断言失败点,对比CDD要求
NotExecuted 测试用例被跳过,未实际执行 前置条件不满足、设备特性不支持、动态跳过 检查skip原因,确认设备是否缺少必要硬件/软件
Error 测试执行过程中发生基础设施异常(如设备断开) USB断开、设备重启、系统服务崩溃 检查设备连接稳定性,查看crash日志
常见误区: NotExecuted 不等于 Pass。如果大量测试项显示 NotExecuted,通常意味着设备缺少关键特性(如 android.hardware.camera)或测试配置错误。必须逐一排查跳过原因,否则可能导致认证失败。
CTS测试状态判定流程 CTS测试状态判定流程 测试用例开始 是否执行? NotExecuted 是否通过? Pass Fail Error 状态判定要点: • 前置条件不满足 → NotExecuted • 断言失败 → Fail • 基础设施异常 → Error • 全部断言通过 → Pass

4.3 日志文件定位方法

当测试结果为 Fail 或 Error 时,需要从日志中提取失败原因。CTS日志按以下层级组织:

  1. 模块级日志:位于 logs/<模块名>/ 目录下,包含该模块所有测试用例的汇总日志。
  2. 用例级日志:位于 logs/<模块名>/<测试用例名>/ 目录下,包含该用例的详细输出。
  3. 设备日志:每个测试用例执行期间抓取的 logcat 日志,文件名通常包含 logcat 关键字。
  4. 崩溃日志:位于 crashes/ 目录下,包含 tombstone、native crash dump 等。
快速定位命令: 在CTS根目录下使用以下命令可以快速找到失败用例的日志:
# 查找所有失败测试用例的日志目录
grep -r 'FAIL' repository/results/2025-03-21_14-30-00/test_result.xml | grep 'testCase' | head -10

# 查看某个具体用例的日志
cat repository/results/2025-03-21_14-30-00/logs/<模块名>/<测试用例名>/logcat.txt

4.4 典型日志分析案例

以下是一个典型的 Fail 日志片段,展示如何从日志中提取失败原因:

--------- beginning of main
03-21 14:35:12.345  1234  5678 D TestRunner: Starting test: testCameraOpen
03-21 14:35:12.456  1234  5678 I CameraService: Camera.open() called
03-21 14:35:12.567  1234  5678 E CameraService: Camera HAL failed to initialize: -38 (ENODEV)
03-21 14:35:12.568  1234  5678 E TestRunner: Assertion failed: Camera.open() should return 0, but got -38
03-21 14:35:12.569  1234  5678 E TestRunner: Test FAILED: testCameraOpen

日志分析要点:

  • 关键行:Camera HAL failed to initialize: -38 (ENODEV) 表明相机HAL初始化失败,错误码 ENODEV 表示设备不存在。
  • 断言失败行:Assertion failed: Camera.open() should return 0, but got -38 直接指出期望返回0,实际返回-38。
  • 排查方向:检查相机HAL实现、设备节点权限、SElinux策略。
日志定位与故障排查流程 日志定位与故障排查流程 1. 打开test_result.html 2. 定位Fail测试项 3. 进入logs/目录 4a. 查看logcat.txt 4b. 查看crashes/ 5. 提取错误信息,定位根因 提示:logcat.txt 包含系统日志,crashes/ 包含native崩溃。两者结合可覆盖90%的失败场景。

4.5 报告解读实战要点

  • 关注模块通过率:单个模块通过率低于100%时,需要逐项排查Fail项。模块通过率是CTS认证的硬性指标。
  • 区分Fail与NotExecuted:Fail必须修复,NotExecuted需要确认是否为设备特性缺失导致。如果设备不支持某项特性,应在 android.hardware 配置中声明。
  • 利用对比报告:将当前报告与基线报告对比,快速识别回归问题。CTS提供了 compare_results 工具。
  • 日志时间戳对齐:使用logcat的时间戳与测试用例执行时间对齐,可以精确定位问题发生的上下文。
高级技巧: 使用 cts-tradefed 的 --retry 命令可以自动重跑失败的测试用例,并生成对比报告。重跑后如果Fail变为Pass,说明问题可能是偶发性的;如果持续Fail,则需要深入分析。