声明式 HTTP API 测试

https://blueprints.launchpad.net/ceilometer/+spec/declarative-http-tests

本文档提出了一套针对 Ceilometer HTTP API 的“灰盒”测试,这些测试由一个或多个人类可读的文本文件驱动,这些文件声明 URL 请求以及预期的响应。这些测试将提供端到端 API 端点的测试,除了确认 API 的功能之外,还将提供清晰易读的 HTTP API 概述。

这套测试是对现有测试的补充,而不是替代。假设几个小型工具,每个工具都执行一项专注的任务,比一个工具执行所有任务更有效。在这种情况下,重点在于遍历 HTTP API 的广度,以确认其运行状况良好并演示预期的行为,而不是验证 API 提供的的数据(单元测试应该执行此操作)。

对 API 的透明度应该带来更好的测试,并最终带来更好的 API。

问题描述

现有的 Ceilometer HTTP API 单元测试被 Python 代码和传统的单元测试基础设施所包围和束缚。当测试的目的既是测试是使 HTTP API 的测试可见时,这些会产生噪音。最应该可见的是 HTTP 和 API。当这些内容不可见时,测试作为开发人员进行更改时发现问题的工具的有效性将受到限制。

集成测试框架 Tempest 存在与上述相同的一些问题,同时也正在进行目的的改进。与其测试所有内容,未来的 Tempest 将演变为有效地测试大多数内容的集成。在这种未来,希望详细确认其系统的项目需要自行进行测试。

Tempest 也更严格地要求测试用例不了解内部细节。本提案将不受此类限制,这对于测试设置机制可能证明很方便。

此外,Tempest 现在是“无分支的”,这意味着相同的测试分支将在 stable/{icehouse|juno} 和 master 上运行。这要求针对新可测试功能进行的测试要么动态地发现这些功能的可用性,要么根据 Tempest 运行的分支显式配置为跳过(两种选择都不理想)。本提案将不受这些复杂性的影响,因为测试将存在于代码树中,因此将以与代码库的其余部分相同的方式进行分支。

提议的变更

为了解决 HTTP 测试中的不足(可读性和完整性),将定义一个新的 tox 目标,该目标运行一系列表示为 HTTP 请求和预期响应的 HTTP 测试。确切的格式应通过讨论确定,因为这类事情总是会引起很多争议。最好尽早解决这个问题。

这套相同的测试也将注册为检查作业,以在代码审查过程中对提出的补丁进行运行。

在理想情况下,测试将对 Ceilometer 通过 HTTP 呈现的所有活动端点提供的每个 URL 运行所有常用的 HTTP 方法。这意味着它应该涵盖即将由 Gnocchi 提供的待处理 v3 API,以及即将弃用的旧 API。

为了确保测试轻量级且快速,将不使用 Web 服务器,并且仅使用一个轻量级数据存储(mongo、sqlite3)进行有限的持久性。这些测试用于测试 Ceilometer 的 HTTP API 方面,因此不是场景测试:我们不需要在每个可用的数据存储上运行这些测试。

“无需 Web 服务器”可以通过使用 wsgi-interceptWebTest 或类似工具来实现。工具的选择应由确定哪种工具最能促进从声明式格式到可以由运行器处理的测试的轻松转换来驱动。

测试的声明式格式需要在人类易于编写和阅读与计算机易于解析之间取得平衡。通常有两种风格

  • 类似于 curl -v 的输出。这具有看起来就像线路上的 HTTP 的优点,但缺点是很难表达部分期望或部分请求。

  • 表示请求和预期响应的字典列表。这易于以 YAML 等通用格式表达,可以很好地处理部分信息,并处理一种继承形式。作者在这方面取得了良好的成功,因此倾向于选择它。

假设后者格式,可能的实现包括

  • 一个测试运行器,它解析 YAML 文件以生成测试,这些测试将被测试框架捕获。除了发出 HTTP 请求和处理响应之外,此运行器还将负责设置:建立必要的服务和其他测试先决条件。

  • 一个目录,其中包含多个 YAML 文件,每个文件代表 API 中的某种事务/场景API 的一个版本中的所有路由。

请注意,本提案未提及客户端代码,因为它正在测试直接 HTTP 请求,而不是对客户端库的调用。这正是重点:客户端库隐藏了 HTTP,而我们试图在这里做的是将 HTTP 交互暴露在审查的严酷光线下。

有一些问题需要解决才能达成完整的解决方案。应该可以在飞行中解决这些问题。这些问题包括

  • 测试的格式是什么?

  • 如何在最小限度的情况下处理 authN 和 authZ?理想情况下,keystone 不会运行。如果是这样,需要做什么?

  • 如何将请求和响应组聚合到单个测试中?一种选择是把每个 YAML 文件当作一个单独的测试。

替代方案

有几种替代方案可以替代 Ceilometer 代码树中独立的声明式 HTTP 测试套件

  • qa 提出规范,用于构建一种通用的解决方案,用于在代码树中进行声明式 HTTP 测试。从长远来看,这将是一个很好的结果,但如果人们能够看到一个可供改进的工作版本,那么这个结果似乎更有可能实现。

  • 不要使用独立的套件,而是将测试集成到更大的、在树中的功能和/或集成测试中。虽然这可能从复杂性管理的角度来看是一个好主意,但它在确保所需目的的紧密关注方面价值有限。

  • 不要使用声明式测试,而是继续使用面向对象的 unittests 风格,这是许多测试中的标准。这样做将违背提案的目的(暴露和表达 HTTP),因此不建议这样做。

  • 在各种存储和 Web 服务器场景下运行测试,以实现对各种情况的最大覆盖率。虽然这可能具有一定的价值,但会导致测试速度变慢并显著增加测试框架的复杂性。速度慢的测试会阻止人们运行它们,而复杂性会导致中断。

  • 什么都不做。使用现有的单元测试和 Tempest 测试。这不是一个好的选择,因为现有的单元测试和 Tempest 测试都没有提供良好的(可读的)覆盖率。

数据模型影响

无。这些测试不应该暴露数据模型。

REST API 影响

这些测试不会增加 API,但希望能够改进它。

安全影响

无。

Pipeline 影响

无。

其他最终用户影响

编写和运行这些测试可能会表明 API 令人困惑且难以使用,这可能会导致改进它。这太棒了。

性能/可扩展性影响

额外的门禁检查作业可能会对性能产生一些影响,但预计这些更改不会影响 Ceilometer 本身的性能。

其他部署影响

无。

开发者影响

如果开发人员添加或更改 HTTP API,则这些更改需要反映在这套测试中。

实现

负责人

主要负责人

chdent

其他贡献者

dbelova

持续维护者

chdent

工作项

  • 确定声明式格式。

  • 确定测试的范围或深度(是否使用 Web 服务器?其他数据存储?)。

  • 编写测试框架。

  • 编写第一轮测试。

  • 与 tox 和 testr 集成。

  • 创建门禁作业。

未来生命周期

随着 API 中功能的添加和删除,此套件中的相应测试需要进行更改。大多数时候,这应该由该功能的实现者来完成,但有时需要进行更大的清理。

同样,如果存储处理成为测试套件的一部分,那么随着新存储系统的实现(或删除),需要处理它们。

依赖项

这项工作是独立的,但可能会增加测试所需的库(例如 wsgi-intercept)。

测试

作为一套测试,该系统将测试自身。但是,它应该包括一些健全性测试,以确保其行为正常。

文档影响

无。

参考资料

请参阅上面的链接和