RFC-0163:测试输出格式

RFC-0163:测试输出格式
状态已接受
区域
  • 测试
说明

定义了 ffx 测试生成的测试输出格式的初始稳定版本,但尚未使用该版本。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2022-02-22
审核日期(年-月-日)2022-05-18

旧版 API 设计文档

此 RFC 之前是作为 API 设计文档提交的,后来在弃用 API 设计文档模板后,转换为 RFC。

摘要

本文档提出了通过 fuchsia SDK 提供的测试工具输出的稳定的基于目录的格式。

目标和用例

借助测试架构,客户端可以一次性安排和执行多个测试,还会为每个测试收集大量诊断工件。ffx test 充当主机工具,客户端可以通过该工具与测试架构进行交互。

调用 ffx test 的自动化工具(例如在 CI 基础架构中运行的工具)需要一种可靠的方式来获取测试执行期间生成的完整结果和工件。目前,这些工具通过解析标准输出获取测试结果,但这种方法很脆弱,无法表达 Test Architecture 收集的全部工件。此设计旨在提供一种经过优化以供机器解析的稳定输出格式。

借助稳定的磁盘格式,开发者还可以在测试运行后检查结果,或与其他开发者共享结果。

ffx test 旨在供 SDK 使用方在树外使用。为确保这些用户的工具不会因工具更新而损坏,该格式必须具有稳定性保证。

此输出格式并非用于取代测试成功或失败的所有信号。例如,ffx test 仍将支持人类可读的输出,以及用于指示成功或失败的返回代码。

背景

单次执行 ffx test 会生成一项测试运行测试运行套件组成,每个套件由测试用例组成。

套件运行是指测试组件的一次执行。测试组件最常通过其网址进行标识,例如 fuchsia-pkg://fuchsia.com/run_test_suite_integration_tests#meta/passing-test-example.cm。在一次测试运行中,可以多次运行同一套件。在这种情况下,有多个单独的套件运行

测试用例是指对套件中包含的单个测试用例的执行。在一次套件运行中,可以多次运行同一测试用例。在本例中,存在多个测试用例

工件是测试架构收集的诊断输出。工件的范围可限定为测试运行、测试套件运行或测试用例。例如,Test Architecture 目前会针对每个测试用例收集标准输出和标准错误输出,但会针对每次运行的测试套件收集 syslog。

设计

概览

测试输出会存储为目录。目录的根目录包含一个 JSON 文件和任意数量的子目录。子目录将包含范围限定为单个测试用例、测试套件或测试运行的工件。JSON 文件包含测试结果、测试执行详情,并列出目录中包含的工件。

目录布局

JSON 文件始终称为 run_summary.json,并且始终位于目录的顶层。run_summary.json 包含整个测试运行、测试运行中的套件运行以及每个套件运行中的测试用例的完整结果集。它还包含每个工件子目录的名称及其中的工件列表。

子目录和子目录中的工件的名称未指定。子目录和工件的实际名称在 run_summary.json 中定义。工件始终位于工件子目录的顶层。

JSON 架构

JSON 架构将放置在 //sdk/schema/ffx_test 下,并通过 SDK 导出。架构演变将依赖于 RFC-0100 中引入的架构版本控制机制。

架构的初始版本在此提交中定义。

按工具划分的使用量

需要解读测试结果的工具应先解析 run_summary.json,这是输出格式中唯一具有已定义位置的文件。run_summary.json 包含完整的结果集以及对所有工件的引用。工具不应假定输出中的任何其他位置都是稳定的。

未知

输出格式可能会根据用户需求进行更新。例如,我们可能会更新格式,以简化我们发现的常见用例中的解析。

易用性

可扩展性和演变

我们预计的主要扩展是添加新的测试状态和工件类型。通常,向架构添加枚举变体和 JSON 字段不会破坏更改,使用输出的工具可以放心地忽略不理解的字段和枚举变体。破坏性更改包括对必填字段的修改以及对目录结构的更改。在这些情况下,系统会按照 RFC-0100 中的策略在 SDK 中生成并发布新版本的 JSON 架构。

类似输出

除了 Fuchsia 之外,还有许多单独的测试框架支持多种机器可读的测试结果格式。例如,googletest 同时支持 JSON 和 XML 输出格式。

测试

测试将主要依赖于单元测试和集成测试,以验证 ffx test 生成的输出是否符合输出格式。

性能注意事项

生成此文件格式预计不会花费太长时间。一个原型实现可保存包含 10 万个测试用例的套件,每个测试用例都有 stdout 和 stderr 工件,生成并保留 run_summary.json 只需不到一秒的时间,run_summary.json 在磁盘上大约为 26 MB。假设有 1,000,000 个用例,相同的原型大约需要 15 秒才能生成 run_summary.json,其磁盘大小约为 256 MB。在所有情况下,原型的最大内存用量大约是磁盘上摘要大小的两倍。

相比之下,Chromium 中的一个大型已知测试套件包含大约 10 万个用例。由于为这么多个用例保存 run_summary.json 只需要不到一秒的时间,因此这不应构成问题。

在 fuchsia.git 中,目前最大的测试套件包含大约 300-400 个测试用例,单个基础架构分片可能包含大约 300 个套件。对于 fuchsia.git,我们打算使用 ffx 测试的多测试功能,该功能会将所有测试用例的结果保存在单个输出目录中。因此,在本例中,我们预计 run_summary.json 中最多会存储约 12 万个用例,估计这些用例在磁盘上占用不到 50 MB 的空间,保存时间约为 1 秒。

开发者会重复运行测试,因此存在许多常见的本地开发流程。例如,开发者可能会重复运行测试,以重现不稳定的失败情况。在这种情况下,我们可以轻松运行数千个测试用例的批处理,而不会超过 10 MB 的内存用量。

安全注意事项

此输出仅用于存储测试生成的结果和工件,这些结果和工件已由测试框架提供,不会引入额外的安全注意事项。

隐私注意事项

此输出仅用于存储测试生成的结果和工件,这些结果和工件已由测试框架提供,不会引入额外的隐私保护注意事项。

缺点和替代方案

输出格式默认支持多次测试套件运行。这会使一次只运行一个测试的客户端的解析变得复杂。一种替代方案是支持一种输出格式,其中包含单次测试套件运行的结果,另一种输出格式则包含多次测试套件运行的结果。虽然这简化了即时解析,但使用多种格式会使分析输出的共享工具变得复杂。

另一种方法是使用多个 JSON 文件来存储测试结果。使用单个文件存储所有测试结果的一个缺点是,与该文件交互的工具必须一次将全部内容保存在内存中。根据原型,我们需要大约 400 万个测试用例,run_summary.json 才会超过 1GB,此时序列化大约需要 1 分钟。由于我们目前的使用场景比这小几个数量级,因此目前还不需要使用多个文件。由于将结果存储在多个文件中会使解析变得复杂,因此我们将使用单个文件。

第三种方法是将所有工件存储在 run_summary.json 中,以进一步简化解析。这样做的缺点是,工件现在也需要保存在内存中。目前收集的最大工件是用于覆盖率的配置数据。在单个基础架构分片中,这些配置数据大约为 500 MB,分布在多个文件中。虽然此配置文件不超过 1GB,但如果同时更改测试分片方式和配置数据表示方式,其大小可能会迅速接近 1GB。