在灯具故障后,py.test 2.3.5没有运行终结器

时间:2013-07-15 22:02:02

标签: python pytest

我正在尝试py.test,因为它声称比模块和会话装置的单元测试更好的支持,但我偶然发现了一个,至少对我而言,奇怪的行为。

考虑以下代码(不要告诉我它是愚蠢的,我知道,它只是一个快速而又脏的黑客来复制行为)(我在Windows 7上运行Python 2.7.5 x86)     进口口     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

为模块调用一次fixture,并在测试结束时调用一次。

然后如果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的预期行为吗?

谢谢,加布里埃尔

1 个答案:

答案 0 :(得分:2)

这里有三个问题:

  • 您应该在执行要撤消的操作后注册终结器。所以先调用makedirs()然后注册终结器。这是固定装置的一般问题,因为通常的拆解代码只能在成功创建的情况下运行

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

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

谢谢,holger