我使用 testinfra 和 ansible 传输。它提供了具有 ansible
的 host
固定装置,因此我可以执行 host.ansible.get_variables()
。
现在我需要根据此库存中的值创建测试参数化。
库存:
foo:
hosts:
foo1:
somedata:
- data1
- data2
我想编写一个测试来测试 list 中每个主机的某些数据中的每个“数据”。 “每个主机”部分由 testnfra 处理,但我在测试参数化方面遇到了困难:
@pytest.fixture
def somedata(host):
return host.ansible.get_variables()["somedata"]
@pytest.fixture(params=somedata):
def data(request):
return request.param
def test_data(host, data):
assert 'data' in data
两种方法我都尝试过:
@pytest.fixture(params=somedata)
->TypeError:“function”对象不可迭代
@pytest.fixture(params=somedata())
->直接调用Fixture“somedata”。 Fixtures 并不意味着直接调用...
我该怎么做?我知道我无法更改测试时的测试数量,但我很确定我在收集时有相同的库存,所以,理论上,这是可行的......
最佳答案
在阅读了大量源代码之后,我得出的结论是,在收集时调用固定装置是不可能的。收集时没有固定装置,任何参数化都应该在调用任何测试之前进行。此外,不可能在测试时改变测试数量(因此没有 fixture 可以改变这一点)。
回答我自己关于使用 Ansible inventory 参数化测试函数的问题:这是可能的,但它需要手动读取 inventory、hosts 等。有一个特殊的钩子(Hook):pytest_generate_tests
(它是一个功能,而不是固定装置)。
我当前获取由 host_interface
fixture 参数化的任何测试的代码是:
def cartesian(hosts, ar):
for host in hosts:
for interface in ar.get_variables(host).get("interfaces",[]):
yield (host, interface)
def pytest_generate_tests(metafunc):
if 'host_interface' in metafunc.fixturenames:
inventory_file = metafunc.config.getoption('ansible_inventory')
ansible_config = testinfra.utils.ansible_runner.get_ansible_config()
inventory = testinfra.utils.ansible_runner.get_ansible_inventory(ansible_config, inventory_file)
ar = testinfra.utils.ansible_runner.AnsibleRunner(inventory_file)
hosts = ar.get_hosts(metafunc.config.option.hosts)
metafunc.parametrize("host_interface", cartesian(hosts, ar))
关于pytest - 在 pytest 中收集时使用固定装置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57660004/