2

我正在尝试 py.test,因为它声称对模块和会话装置的支持比 unittest 更好,但我偶然发现了一种奇怪的行为,至少对我来说是这样。

考虑以下代码(不要告诉我它很愚蠢,我知道,这只是复制行为的快速而肮脏的黑客行为)(我在 Windows 7 上的 Python 2.7.5 x86 上运行) import os import shutil import pytest

test_work_dir = 'test-work-dir'
tmp = os.environ['tmp']
count = 0

@pytest.fixture(scope='module')
def work_path(request):
    global count
    count += 1
    print('test: ' + str(count))
    test_work_path = os.path.join(tmp, test_work_dir)

    def cleanup():
        print('cleanup: ' + str(count))
        if os.path.isdir(test_work_path):
            shutil.rmtree(test_work_path)
    request.addfinalizer(cleanup)
    os.makedirs(test_work_path)
    return test_work_path

def test_1(work_path):
    assert os.path.isdir(work_path)
def test_2(work_path):
    assert os.path.isdir(work_path)
def test_3(work_path):
    assert os.path.isdir(work_path)

if __name__ == "__main__":
    pytest.main(['-s', '-v', __file__])

如果test_work_dir不存在,那么我将获得预期的行为:

platform win32 -- Python 2.7.5 -- pytest-2.3.5 -- C:\Programs\Python\27-envs\common\Scripts\python.exe
collecting ... collected 4 items

py_test.py: [doctest] PASSED
py_test.py:34: test_1 test: 1
cleanup: 1
PASSED
py_test.py:38: test_2 PASSED
py_test.py:42: test_3 PASSEDcleanup: 1

为模块调用一次夹具,并在测试结束时调用一次清理。

然后,如果test_work_dir存在,我会期望类似于 unittest 的东西,该夹具被调用一次,它失败OSError,需要它的测试不会运行,清理被调用一次并再次建立世界和平。

但是......这就是我所看到的:

py_test.py: [doctest] PASSED
py_test.py:34: test_1 test: 1
ERROR
py_test.py:38: test_2 test: 2
ERROR
py_test.py:42: test_3 test: 3
ERROR

尽管夹具失败,所有测试都运行,应该scope='module'为每个测试调用一次夹具,并且终结器从未调用!

我知道夹具中的异常不是好的策略,但是真正的夹具很复杂,如果我可以依靠每个终结器集的执行直到故障点,我宁愿避免用 try 块填充它们。我不想在失败后去寻找测试工件。此外,当他们需要的所有固定装置都没有到位时,尝试运行测试是没有意义的,而且充其量会使它们变得不稳定。

这是 py.test 在夹具失败的情况下的预期行为吗?

谢谢,加布里埃尔

4

1 回答 1

2

这里有三个问题:

  • 您应该在执行要撤消的操作后注册终结器。所以首先调用 makedirs() 然后注册终结器。这是固定装置的普遍问题,因为通常拆解代码只有在成功创建某些东西时才能运行

  • pytest-2.3.5 有一个错误,如果fixture 函数失败,它不会调用终结器。我刚刚修复了它,您可以安装 2.4.0.dev7(或更高)版本pip install -i http://pypi.testrun.org -U pytest。它确保即使夹具功能部分失败,也会调用夹具终结器。实际上有点令人惊讶,这并没有更早出现,但我想包括我在内的人们通常只是继续修复固定装置,而不是深入研究具体发生的事情。所以感谢您在这里发帖!

  • 如果模块范围的夹具功能失败,则需要该夹具的下一个测试仍将再次触发夹具功能的执行,因为它可能是间歇性故障。按道理,pytest 应该记住给定范围的失败,而不是重试执行。如果你这么认为,请打开一个问题,链接到这个 stackoverflow 讨论。

谢谢,霍尔格

于 2013-07-17T08:35:12.177 回答