测试(QA 和 CI)

OpenStack 项目拥有强大的自动化测试。一般来说,我们认为未经过测试的东西就是损坏的。OpenStack 是一个极其复杂的软件套件,主要设计用于与其他软件交互,这些软件可以在各种配置中运行。在这种情况下,手动本地化测试可能不足以胜任。默认情况下,所有测试都是使用当前版本的依赖项完成的,这些依赖项由 upper-constraints.txt 文件在 openstack/requirements 仓库中集中管理。使用 lower-constraints.txt 文件测试依赖项的下限是可选的。

测试类型

OpenStack 项目采用多种测试方法

单元测试

这些测试通常设计用于验证单个方法或类,并验证代码在所有输入情况下的运行方式是否符合设计。它们可能使用模拟或虚假对象来简化与测试区域外部组件的交互。

大多数项目都有大量的单元测试,并期望这些测试能够实现近乎完整的代码覆盖率。对项目代码的更改通常应包括添加测试的更改。

功能测试

功能测试验证项目在运行中的状态(例如,如果项目是一个 API 服务器,则服务器将实际运行),但与外部组件的交互保持在最低限度。这可以通过使用其他组件的虚假驱动程序或这些组件的更简单实现来实现。

功能测试预计能够捕获在更易于理解和调试的环境中大多数实际的运行错误,而不是完整的集成测试环境。

集成测试

集成测试包括项目和所有相关组件以尽可能真实的方式运行。目标是在生产环境中出现之前,识别仅可能在生产环境中出现的错误。通常,如果在集成测试中发现错误,则可能表明功能测试存在差距。

风格检查

当大量开发人员一起在一个项目的代码库上工作时,拥有统一的代码风格通常很有用。风格检查(例如 Python 的 pep8)是一种确保所有贡献者保持一致代码风格的自动化方法。

自动化测试系统

OpenStack 项目通常可以由开发人员在提交更改之前本地测试。但是,并非所有开发人员都能访问足够的测试资源来运行所有测试,而且,项目审查人员不能假定开发人员已执行所有相关的测试。因此,OpenStack 项目可以定义一组在项目每次更改时自动运行的测试作业。这些作业由名为 Zuul 的工具运行,结果直接发布在 Gerrit 代码审查系统评论中。

为了促进项目以标准化的方式与自动化测试系统交互,技术委员会已采用 一致的测试接口,该接口描述了项目为开发人员和自动化系统运行测试必须提供的设施。

项目闸门

OpenStack 项目不允许任何人直接将代码合并到源代码仓库。相反,核心审查团队的任何成员都可以批准更改以供包含,但实际的合并过程是完全自动化的。批准后,更改将再次通过测试运行,并且只有当更改通过所有测试时,才会被合并。

此过程可确保开发的主分支始终正常工作(至少在测试基础设施可以确定的情况下)。这意味着开发人员可以在任何时候签出仓库的副本并开始工作,而不必担心它是否实际运行。

这对于我们社区的平等结构也很重要。由于没有项目成员能够覆盖自动化测试系统的结果,因此没有人会试图在自己的权威下合并更改,而可能错误地认为自己比测试系统更了解更改是否正常工作。

有关自动化测试基础设施本身的更多信息,包括如何配置和使用它,请参阅 OpenDev 手册

如何处理测试失败

如果 Zuul 报告补丁的测试失败,第一步应该是确定出了什么问题。您会很想再次检查补丁,看看它是否再次失败,但请不要这样做。 CI 测试资源是一种非常稀缺的资源(而且越来越稀缺),因此请在要求系统重新运行测试时要格外节俭。

注意

请不要永远简单地 recheck 而没有理由。请始终尝试确定导致失败的原因,并给出一些有意义的描述。例如,可以写出失败的测试名称或有关在哪个作业/测试用例中出错的其他信息。请尽量避免像 recheck - unrelated failure 这样的评论,因为这些评论几乎与简单地 recheck 相同。

在您请求重新检查之前,务必遵守以下准则

  1. 首先,您应该检查失败作业的日志。查找作业失败的原因,无论是测试失败还是设置失败,例如 DevStack 运行失败或作业超时。您应该始终从怀疑失败是所提议补丁的结果开始此过程,但也要关注问题是否无关。

  2. 如果失败可能是由所提议的补丁引起的,您应该尽可能尝试在本地重现失败。这将使您能够修改更改并重新提交,从而更有可能获得通过的运行。

  3. 如果失败似乎与手头的补丁完全无关,请查找一些指示出了什么问题的迹象。只有在您这样做之后,才应该要求 Zuul 重新运行测试。为此,请在补丁上评论重新检查命令和原因。示例包括

    recheck nova timed out waiting for glance

    recheck glance lost connection to mysql

    recheck cinder failed to detach volume

  4. 重新检查命令的黄金标准是 recheck bug #XXXXXXX,它直接引用已知正在处理的问题。这样做有助于增加该错误的关注度,并启用统计跟踪,以便社区了解哪些错误阻碍了 CI 系统中的最多人。

  5. 在某些情况下,可能完全不清楚为什么会发生故障。在这种情况下,您可以重新检查,理由是“不确定发生了什么,重新检查以获取另一个数据点”。

  6. 如果问题的根本原因尚不清楚,但也很清楚它与补丁无关,您还可以将失败的测试名称添加到重新检查命令中,例如 recheck - failed test tempest.api.network.test_ports.test_example

  7. 如果重新检查在后续运行中导致类似的失败,最好通过邮件列表或 IRC 联系负责您认为正在失败的服务项目团队,并寻求有关问题是否已知并正在处理的指导,因为可能存在针对该问题的补丁,但尚未合并,您可以 Depends-On 以继续前进。

  8. 如果相同的失败发生多次且尚未报告,强烈建议您针对受影响的项目(或项目)打开一个错误,并将其用于重新检查。

确定失败原因的建议

这更像是一种艺术而不是科学,但这里有一些想法

  • 首先检查 job-output.txt 文件,看看作业是在运行测试时失败,还是在设置运行时失败。

  • 如果看起来是测试失败,testr_results.html 文件通常非常有助于查看单个失败。

  • 如果测试失败,请尝试确定哪些服务正在该测试中使用。快速扫描这些服务的日志,查找 ERROR 行,尤其是与测试失败相对应的跟踪信息。例如,如果测试是计算失败,无法附加卷,那么查看 n-apin-cpuc-apic-vol 日志会很好,因为 Nova 和 Cinder 都参与了该过程。

  • 基于 tempest 的作业中的测试失败通常会打印出资源 ID,例如实例或卷 UUID。使用这些 ID 在相关日志中搜索与测试失败相关的错误和警告。

  • 查看测试失败的时间戳也可以帮助定位服务日志中的相关行。

检查其他作业结果的状态

每个 Zuul CI 作业结果都发送到 Opensearch 服务。该服务在 Zuul 作业状态为 Failure 时非常有用。检查给定的错误是否未在另一个项目中发生,或者它是否最近没有定期出现,这将有助于更快地识别问题或通知 OpenStack 社区有关该问题。

要检查 Opensearch 服务,您需要使用以下凭据登录