在Pytest中在收集时间使用固定装置

时间:2019-08-26 14:35:27

标签: pytest ansible-inventory testinfra

我将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())

我该怎么做?我知道我无法在测试时更改测试数量,但我可以肯定的是,在收集时我拥有相同的清单,因此,从理论上讲,这是可行的...

2 个答案:

答案 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))