单元测试
单元测试是针对特定库或模块的小型隔离测试。Ansible中的单元测试目前是唯一一种在Ansible的持续集成过程中从python驱动测试的方法。这意味着在某些情况下,测试范围可能不仅仅局限于单元。
可用测试
单元测试可以在test/units中找到。请注意,测试的目录结构与lib/ansible/
的目录结构匹配。
运行测试
注意
要使用docker运行单元测试,请始终使用默认的docker镜像,方法是传递--docker
或--docker default
参数。
可以通过以下方式运行整个代码库的Ansible单元测试:
cd /path/to/ansible/source
source hacking/env-setup
ansible-test units --docker -v
针对单个文件:
ansible-test units --docker -v apt
或针对特定Python版本:
ansible-test units --docker -v --python 2.7 apt
如果针对模块以外的项目运行单元测试(例如模块实用程序),请指定完整的文件路径:
ansible-test units --docker -v test/units/module_utils/basic/test_imports.py
有关高级用法,请参见在线帮助。
ansible-test units --help
您也可以通过打开拉取请求在Ansible的持续集成系统中运行测试。这将根据您在拉取请求中所做的更改自动确定要运行哪些测试。
安装依赖项
如果您使用--docker
或--venv
选项运行ansible-test
,则无需手动安装依赖项。
否则,您可以使用--requirements
选项安装依赖项,这将安装单元测试所需的所有依赖项。例如:
ansible-test units --python 2.7 --requirements apache2_module
单元测试依赖项列表可在test/units/requirements.txt中找到。
这并不包括ansible-test
本身的单元测试依赖项列表,该列表可在test/lib/ansible_test/_data/requirements/units.txt中找到。
另请参见适用于所有测试命令的约束条件。
扩展单元测试
警告
单元测试不是什么
如果您开始编写需要外部服务的测试,那么您可能正在编写集成测试,而不是单元测试。
单元测试结构
Ansible通过pytest驱动单元测试。这意味着测试可以编写为简单的函数(包含在任何文件名中,例如test_<something>.py
)或类。
这是一个函数示例:
#this function will be called simply because it is called test_*()
def test_add():
a = 10
b = 23
c = 33
assert a + b == c
这是一个类示例:
import unittest
class AddTester(unittest.TestCase):
def SetUp():
self.a = 10
self.b = 23
# this function will
def test_add():
c = 33
assert self.a + self.b == c
# this function will
def test_subtract():
c = -13
assert self.a - self.b == c
这两种方法在大多数情况下都能正常工作;基于函数的接口更简单快捷,因此如果您只是尝试为模块添加一些基本测试,那么这可能是您应该开始的地方。基于类的测试允许更整洁地设置和拆除先决条件,因此,如果您对模块有许多测试用例,您可能需要重构以使用它。
在测试中使用简单的assert
函数进行断言将提供关于失败原因的完整信息,以及在断言期间调用的函数的回溯。这意味着建议使用普通断言而不是其他外部断言库。
许多单元测试套件都包含在多个模块之间共享的函数,尤其是在网络领域。在这些情况下,会在同一目录中创建一个文件,然后直接包含该文件。
模块测试用例公共代码
尽可能在test/units/目录结构中保持公共代码的特定性。不要从当前或父目录之外的目录导入公共单元测试代码。
不要从单元测试中导入其他单元测试。任何公共代码都应该放在不是测试本身的专用文件中。
Fixture文件
要模拟从设备获取结果,或提供来自外部库的其他复杂数据结构,可以使用fixtures
读取预生成的数据。
您可以查看fixtures如何在cpuinfo事实测试中使用。
如果您正在模拟API,您可能会发现Python placebo很有用。有关更多信息,请参见单元测试Ansible模块。
新增或更新单元测试的代码覆盖率
新代码将缺失于codecov.io代码覆盖率报告中(参见测试Ansible),因此需要本地报告。大多数ansible-test
命令允许您收集代码覆盖率;这在指示扩展测试的位置时特别有用。
要收集覆盖率数据,请将--coverage
参数添加到您的ansible-test
命令行:
ansible-test units --coverage apt
ansible-test coverage html
结果将写入test/results/reports/coverage/index.html
可以使用多种不同的格式生成报告:
ansible-test coverage report
- 控制台报告。ansible-test coverage html
- HTML报告。ansible-test coverage xml
- XML报告。
要在测试运行之间清除数据,请使用ansible-test coverage erase
命令。有关生成覆盖率报告的更多信息,请参见测试Ansible和集合。
另请参见
- 单元测试Ansible模块
单元测试模块的特殊注意事项
- 测试Ansible和集合
在本地运行测试,包括收集和报告覆盖率数据
- Python 3文档 - 26.4. unittest — 单元测试框架
Python 3中unittest框架的文档
- Python 2文档 - 25.3. unittest — 单元测试框架
最早支持的unittest框架的文档 - 来自Python 2.6
- pytest:帮助您编写更好的程序
pytest的文档 - 实际用于运行Ansible单元测试的框架