理解集成测试
注意
有些集合没有集成测试。
集成测试是模块和插件的功能测试。通过集成测试,我们检查模块或插件是否满足其功能要求。简单来说,我们检查功能是否按预期工作,并且用户获得模块或插件文档中描述的结果。
集合中使用了两种集成测试
使用 Ansible 角色的集成测试
使用
runme.sh
的集成测试。
本节重点介绍使用 Ansible 角色的集成测试。
集成测试使用调用这些模块的 playbook 检查模块。测试传递独立的参数及其组合,检查模块或插件使用 assert 模块报告的内容,以及每个任务后系统的实际状态。
集成测试示例
假设我们要测试使用 name
参数调用的 postgresql_user
模块。我们期望该模块根据提供的 name
参数值创建一个用户,并报告系统状态已更改。我们不能只依赖模块报告的内容。为了确保用户已创建,我们使用另一个模块查询我们的数据库,以查看用户是否存在。
- name: Create PostgreSQL user and store module's output to the result variable
community.postgresql.postgresql_user:
name: test_user
register: result
- name: Check the module returns what we expect
assert:
that:
- result is changed
- name: Check actual system state with another module, in other words, that the user exists
community.postgresql.postgresql_query:
query: SELECT * FROM pg_authid WHERE rolename = 'test_user'
register: query_result
- name: We expect it returns one row, check it
assert:
that:
- query_result.rowcount == 1
有关集成测试的详细信息
Ansible 集成测试的基本实体是 target
。target 是一个存储在集合仓库的 tests/integration/targets
目录中的Ansible 角色。目标角色包含测试模块所需的一切。
目标的名称包含它们测试的模块或插件名称。以 setup_
开头的目标名称通常在模块和插件目标开始执行之前作为依赖项执行。有关详细信息,请参阅创建新的集成测试。
要运行集成测试,我们使用包含在 ansible-core
和 ansible
软件包中的 ansible-test
实用程序。有关详细信息,请参阅运行集成测试。完成集成测试后,请参阅创建您的第一个集合拉取请求,了解如何提交拉取请求。
为集合的集成测试做准备
为开发集成测试做准备
确定集成测试是否已存在。
ansible-test integration --list-targets
如果集合已经有集成测试,它们会存储在集合仓库的 tests/integration/targets/*
子目录中。
如果您使用 bash
并且系统上使用 pip
安装了 argcomplete
软件包,您还可以获得完整的目标列表。
ansible-test integration <tab><tab>
或者,您可以检查 tests/integration/targets
目录是否包含与模块名称相同的对应目录。例如,community.postgresql
集合的 postgresql_user
模块的测试存储在集合仓库的 tests/integration/targets/postgresql_user
目录中。如果没有相应的目标,则该模块没有集成测试。在这种情况下,请考虑为模块添加集成测试。有关详细信息,请参阅创建新的集成测试。
关于覆盖率的建议
错误修复
在修复代码之前,在 适当的测试目标 中创建一个测试用例,该用例重现问题报告者提供并在 Steps to Reproduce
问题部分中描述的错误。运行测试。
如果您未能重现该错误,请要求报告者提供其他信息。该问题可能与环境设置有关。有时,特定的环境问题无法在集成测试中重现,在这种情况下,需要问题报告者或其他感兴趣的用户进行手动测试。
重构代码
在重构代码时,请务必检查相关选项是否在相应的测试目标中涵盖。不要假设如果测试目标存在,则一切都已涵盖。
覆盖模块/新功能
在覆盖模块时,请分别覆盖其所有选项及其有意义的组合。应针对以下各项测试模块的每种可能用法
幂等性 - 重新运行任务是否报告没有更改?
检查模式 - 干运行任务的行为是否与实际运行相同?它是否没有进行任何更改?
返回值 - 模块在不同条件下是否一致地返回值?
每个测试操作必须至少测试以下次数
如果支持,在检查模式下执行操作。这应表示更改。
使用另一个模块检查更改是否实际上
没有
进行。实际执行该操作。这应表示更改。
使用另一个模块检查更改是否已实际进行。
再次在检查模式下执行该操作。这应表示
没有
更改。再次执行该操作,这次是真实的执行。这应该表明
没有
更改。
要检查一个任务
将任务的结果注册为一个变量,例如,
register: result
。使用assert模块,检查
是否
- result is changed
。预期的返回值。
如果模块更改了系统状态,请使用至少一个其他模块检查实际的系统状态。例如,如果模块更改了一个文件,我们可以通过在测试任务之前和之后使用stat模块检查其校验和来检查该文件是否已更改。
如果模块支持检查模式,则使用
check_mode: true
运行相同的任务。使用其他模块检查实际的系统状态是否未更改。覆盖模块必须失败的情况。使用
ignore_errors: true
选项,并使用assert
模块检查返回的消息。
示例
- name: Task to fail
abstract_module:
...
register: result
- name: Check the task fails and its error message
assert:
that:
- result is failed
- result.msg == 'Message we expect'
以下是总结
覆盖选项及其合理的组合。
检查返回值。
如果支持,覆盖检查模式。
使用其他模块检查系统状态。
检查模块必须失败的情况和错误消息。