我将testinfra与ansible运输一起使用。它提供了具有host
的{{1}}治具,所以我可以做ansible
。
现在,我需要根据此清单中的值创建测试的参数化。
库存:
host.ansible.get_variables()
我想编写一个测试,以针对清单中的每个主机测试一些数据中的每个“数据”。 “每个主机”部分由testnfra处理,但我在测试的参数化方面苦苦挣扎:
foo:
hosts:
foo1:
somedata:
- data1
- data2
我尝试过两种方式:
@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' object is not iterable
-> @pytest.fixture(params=somedata())
我该怎么做?我知道我无法在测试时更改测试数量,但我可以肯定的是,在收集时我拥有相同的清单,因此,从理论上讲,这是可行的...
答案 0 :(得分:0)
您应该使用辅助函数而不是夹具来参数化另一个夹具。夹具不能用作pytest中的装饰器参数。
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
这假定主机不是灯具。
如果主机是固定装置,则有解决方法。您应该将参数写入tmp文件或环境变量中,并使用辅助函数进行读取。
import os
@pytest.fixture(autouse=True)
def somedata(host):
os.environ["host_param"] = host.ansible.get_variables()["somedata"]
def get_params():
return os.environ["host_param"] # do some clean up to return a list instead of a string
@pytest.fixture(params=get_params()):
def data(request):
return request.param
def test_data(host, data):
assert 'data' in data
答案 1 :(得分:0)
阅读了大量源代码后,我得出结论,在采集时无法调用灯具。收集时没有固定装置,在调用任何测试之前应进行任何参数化。而且,不可能在测试时更改测试数量(因此没有固定装置可以更改)。
回答有关使用Ansible清单对测试功能进行参数设置的我自己的问题:可以,但是需要手动读取清单,主机等。对此有一个特殊的钩子:pytest_generate_tests
(这是一个功能,不是夹具)。
我目前通过host_interface
夹具参数化测试的代码是:
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))