本文简要介绍了测试映射,并说明了如何在 Android 开源项目 (AOSP) 中开始配置测试。
关于测试映射
测试映射是一种基于 Gerrit 的方法,使开发者可以直接在 Android 源代码树中创建预提交和后提交测试规则,并将要测试的分支和设备的决策留给测试基础架构。 测试映射定义是名为 TEST_MAPPING
的 JSON 文件,您可以将其放置在任何源目录中。
Atest 可以使用 TEST_MAPPING
文件在关联的目录中运行预提交测试。 通过测试映射,您可以使用 Android 源代码树内的最小更改将同一组测试添加到预提交检查中。
请参阅以下示例
测试映射依赖于 Trade Federation (TF) 测试框架 来执行测试和报告结果。
定义测试组
测试映射使用测试组对测试进行分组。 测试组的名称可以是任何字符串。 例如,presubmit 可以是在验证更改时运行的一组测试的名称。 postsubmit 可以是用于在合并更改后验证 build 的测试。
软件包构建脚本规则
为了使 Trade Federation 测试框架 为给定的 build 运行测试模块,这些模块必须为 Soong 设置 test_suites
,或者为 Make 设置 LOCAL_COMPATIBILITY_SUITE
,以用于这两个套件之一。
general-tests
适用于不依赖于设备特定功能(例如,大多数设备没有的供应商特定硬件)的测试。 大多数测试都应位于general-tests
套件中,即使它们特定于一个 ABI 或位宽或硬件功能(如 HWASan)(每个 ABI 都有单独的test_suites
目标),即使它们必须在设备上运行。device-tests
适用于依赖于设备特定功能的测试。 这些测试通常位于vendor/
下。 设备特定 仅指 单个 设备独有的功能,因此这适用于 JUnit 测试以及 GTest 测试(即使 GTest 测试是 ABI 特定的,通常也应标记为general-tests
)。
示例
Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests
配置要在测试套件中运行的测试
为了使测试在测试套件内运行,测试必须
- 不得有任何 build 提供程序。
- 完成后必须清理,例如,删除测试期间生成的任何临时文件。
- 必须将系统设置更改为默认值或原始值。
不应假定设备处于某种状态,例如,root 就绪。 大多数测试不需要 root 权限即可运行。 如果测试必须需要 root 权限,则应在其
AndroidTest.xml
中使用RootTargetPreparer
指定,如以下示例中所示。<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
创建测试映射文件
对于需要测试覆盖率的目录,添加一个类似于 示例 的 TEST_MAPPING
JSON 文件。 这些规则确保在触摸该目录或其任何子目录中的任何文件时,测试会在预提交检查中运行。
遵循示例
这是一个 TEST_MAPPING
文件示例(它是 JSON 格式,但支持注释)。
{
"presubmit": [
// JUnit test with options and file patterns.
{
"name": "CtsWindowManagerDeviceTestCases",
"options": [
{
"include-annotation": "android.platform.test.annotations.RequiresDevice"
}
],
"file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
},
// Device-side GTest with options.
{
"name" : "hello_world_test",
"options": [
{
"native-test-flag": "\"servicename1 servicename2\""
},
{
"native-test-timeout": "6000"
}
]
}
// Host-side GTest.
{
"name" : "net_test_avrcp",
"host" : true
}
],
"postsubmit": [
{
"name": "CtsDeqpTestCases",
"options": [
{
// Use regex in include-filter which is supported in AndroidJUnitTest
"include-filter": "dEQP-EGL.functional.color_clears.*"
}
]
}
],
"imports": [
{
"path": "frameworks/base/services/core/java/com/android/server/am"
}
]
}
设置属性
在 示例 中,presubmit
和 postsubmit
是每个测试组的名称。 有关测试组的更多信息,请参阅定义测试组。
您可以在 name
属性的值中设置测试模块的名称或 Trade Federation 集成测试名称(测试 XML 文件的资源路径,例如,uiautomator/uiautomator-demo
)。 请注意,name
字段不能使用类 name
或测试方法 name
。 要缩小要运行的测试范围,请使用诸如 include-filter
之类的选项。 请参阅 include-filter
示例用法。
测试的 host
设置指示测试是否是在主机上运行的无设备测试。 默认值为 false
,表示测试需要设备才能运行。 支持的测试类型包括用于 GTest 二进制文件的 HostGTest
和用于 JUnit 测试的 HostTest
。
file_patterns
属性允许您设置正则表达式字符串列表,用于匹配任何源代码文件的相对路径(相对于包含 TEST_MAPPING
文件的目录)。 在 示例 中,仅当 Java 文件以 Window
或 Activity
开头时,测试 CtsWindowManagerDeviceTestCases
才会在预提交中运行,该文件与 TEST_MAPPING
文件或其任何子目录位于同一目录中。 反斜杠 (\\) 需要转义,因为它们位于 JSON 文件中。
imports
属性允许您在其他 TEST_MAPPING
文件中包含测试,而无需复制内容。 导入路径的父目录中的 TEST_MAPPING
文件也包含在内。 测试映射允许嵌套导入; 这意味着两个 TEST_MAPPING
文件可以相互导入,并且测试映射可以合并包含的测试。
options
属性包含其他 Tradefed 命令行选项。
要获取给定测试的可用选项的完整列表,请运行
tradefed.sh run commandAndExit [test_module] --help
有关选项如何工作的更多详细信息,请参阅Tradefed 中的选项处理。
使用 Atest 运行测试
要在本地执行预提交测试规则
- 转到包含
TEST_MAPPING
文件的目录。 运行命令
atest
将运行在当前目录及其父目录的 TEST_MAPPING
文件中配置的所有预提交测试。 Atest 定位并运行两个预提交测试(A 和 B)。
这是在当前工作目录 (CWD) 和父目录中的 TEST_MAPPING
文件中运行预提交测试的最直接方法。 Atest 定位并使用 CWD 及其所有父目录中的 TEST_MAPPING
文件。
结构化源代码
此示例演示了如何在整个源代码树中配置 TEST_MAPPING
文件。
src
├── project_1
│ └── TEST_MAPPING
├── project_2
│ └── TEST_MAPPING
└── TEST_MAPPING
src/TEST_MAPPING
的内容
{
"presubmit": [
{
"name": "A"
}
]
}
src/project_1/TEST_MAPPING
的内容
{
"presubmit": [
{
"name": "B"
}
],
"postsubmit": [
{
"name": "C"
}
],
"other_group": [
{
"name": "X"
}
]}
src/project_2/TEST_MAPPING
的内容
{
"presubmit": [
{
"name": "D"
}
],
"import": [
{
"path": "src/project_1"
}
]}
指定目标目录
您可以指定目标目录以在该目录的 TEST_MAPPING
文件中运行测试。 以下命令运行两个测试 (A, B)
atest --test-mapping src/project_1
运行后提交测试规则
您还可以使用此命令来运行在 src_path
(默认为 CWD)及其父目录的 TEST_MAPPING
中定义的后提交测试规则。
atest [--test-mapping] [src_path]:postsubmit
仅运行不需要设备的测试
您可以使用 Atest 的 --host
选项仅运行针对不需要设备的主机配置的那些测试。 如果没有此选项,Atest 将运行两个测试:需要设备的测试和在不需要设备的主机上运行的测试。 这些测试在两个单独的套件中运行。
atest [--test-mapping] --host
识别测试组
您可以在 Atest 命令中指定测试组。 以下命令运行与 src/project_1
目录中的文件相关的所有 postsubmit
测试,该目录仅包含一个测试 (C)。
或者,您可以使用 :all
运行所有测试,而与组无关。 以下命令运行四个测试 (A, B, C, X)
atest --test-mapping src/project_1:all
包括子目录
默认情况下,使用 Atest 在 TEST_MAPPING
中运行测试仅运行在 CWD(或给定目录)及其父目录中的 TEST_MAPPING
文件中配置的预提交测试。 如果要在子目录中的所有 TEST_MAPPING
文件中运行测试,请使用 --include-subdir
选项强制 Atest 也包含这些测试。
atest --include-subdir
如果没有 --include-subdir
选项,Atest 仅运行测试 A。 使用 --include-subdir
选项,Atest 运行两个测试 (A, B)。
支持行级注释
您可以添加行级 //
格式的注释,以使用后续设置的描述来充实 TEST_MAPPING
文件。 ATest 和 Trade Federation 预处理 TEST_MAPPING
为没有注释的有效 JSON 格式。 为了保持 JSON 文件的整洁,仅支持行级 //
格式的注释。
示例
{
// For presubmit test group.
"presubmit": [
{
// Run test on module A.
"name": "A"
}
]
}