Pytest:如何确保首先确定某个灯具

时间:2018-10-11 16:41:03

标签: python pytest

我在a_file中有一些数据需要参数化我的灯具。因此,我编写了一个辅助函数,该函数返回a_list,其中填充了来自文件的数据。现在,我可以通过@pytest.fixture(params=a_list)轻松设置灯具的参数。似乎直截了当吧?

这里的问题是a_file是由另一个夹具生成的,并且pytest似乎在夹具实际创建文件之前调用了依赖于该文件的帮助程序。由于这种行为,将引发FileNotFoundError

我的代码如下:

def helper_returning_list_from_a_file():
    with open("a_file") as a_file:
        a_list = a_file.readlines()

    return a_list

@pytest.fixture(scope="session")
def create_file_fixture(depends_on_other_fixtures):
    # create "a_file" here

@pytest.fixture(params=helper_returning_list_from_a_file())
def a_fixture_which_is_parametrized_with_data_from_a_file(request):
    return request.param

def test_which_uses(a_fixture_which_is_parametrized_with_data_from_a_file):
    assert False

添加create_file_fixture必须是一个灯具,不能转换为普通功能,因为它取决于其他灯具。


我已经尝试过的东西

最明显的解决方案是确保在执行需要该文件的辅助函数之前创建该文件。

因此我

  • 向灯具添加了create_file_fixture的依赖项,该依赖项应如下设置参数:

    @pytest.fixture(params=helper_returning_list_from_a_file())
    def a_fixture_which_is_parametrized_with_data_from_a_file(create_file_fixture, request):
        return request.param
    
  • autouse标志添加到用于创建文件的装置中,如下所示:

    @pytest.fixture(scope="session", autouse=True)
    def create_file_fixture:
        # create "a_file" here
    

但是pytest仍然会首先调用助手函数,这将导致与上述相同的错误。


问题

如何确保首先执行create_file_fixture


可能的解决方案

我认为可能的解决方案是将辅助功能也转换为灯具。因此,我可以轻松地在其中添加依赖项,该依赖项将指示pytest应该按什么顺序执行固定装置。看起来像这样:

@pytest.fixture()
def fixture_returning_list_from_a_file(create_file_fixture):
with open("a_file") as a_file:
    a_list = a_file.readlines()

return a_list

这将解决我的文件不存在的问题,但这对我也不起作用,因为它导致了另一个我在这里描述的问题:parametrizing a test with a list returned from a fixture

1 个答案:

答案 0 :(得分:2)

该错误并非由pytest引起。这是由于在Python解释器加载模块时(通常在到达pytest之前)会调用您的helper函数。

不幸的是,您不能从一个灯具产生一个以上的值,也不能对懒惰的生成器进行参数化。原因是必须在运行任何夹具或测试之前计算完整图形,这意味着要预先了解所有参数,如this failed feature request中所述。 @Hoefling's comment建议了一种解决此问题的方法。我会建议一种可能不那么pytest-thonic,但仍然可以工作的方法。

为确保您的文件是预先创建的,并且整个列表都可用于参数化,请不要使其固定不变:只需将其作为模块加载代码的一部分运行,并将列表作为模块属性即可。这不会阻止您在其他地方使用它。如果多个测试模块使用同一列表,则可以将其放入单独的非测试模块中,然后将其导入需要它的测试中。

def create_file_function():
    # create "a_file" here
    return 'a_file'

def helper_returning_list_from_a_file():
    with open(create_file_function()) as a_file:
        a_list = a_file.readlines()

    return a_list

a_list = helper_returning_list_from_a_file()

@pytest.fixture(params=a_list)
def a_fixture_which_is_parametrized_with_data_from_a_file(request):
    return request.param

def test_which_uses(a_fixture_which_is_parametrized_with_data_from_a_file):
    assert False

我认为让create_file_function返回文件名更加优雅/可配置。

给出a_file,如下所示:

ABC
DEF

pytest -v的输出如下:

============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.4.2, py-1.5.2, pluggy-0.6.0 -- /...
cachedir: .pytest_cache
rootdir: /..., inifile:
plugins: remotedata-0.2.0, pep8-1.0.6, openfiles-0.2.0, doctestplus-0.1.2, arraydiff-0.2
collected 2 items                                                              

52765085.py::test_which_uses[ABC\n] PASSED                                [ 50%]
52765085.py::test_which_uses[DEF] PASSED                                  [100%]

=========================== 2 passed in 0.01 seconds ===========================