11

我正在运行在执行期间创建大量大文件的测试。为此,如果测试通过,我想删除 tmpdir 目录。但是如果测试失败,则 tmpdir 的内容应该保持不变。

我知道如何确定测试结果:

from _pytest.runner import runtestprotocol

def pytest_runtest_protocol(item, nextitem):
    reports = runtestprotocol(item, nextitem=nextitem)
    for report in reports:
        if report.when == 'call':
            # value will be set to passed or filed
            test_outcome = report.outcome
            # But what next?

return True

但我不知道如何找出创建的 tmpdir 目录的路径。

4

2 回答 2

4

您应该创建一个 tmpdir 固定装置来创建 tempdir,将其传递到您的代码中,然后将其删除。

此外,fixture 必须设置为始终删除 tempdir,即使失败也是如此。否则,您可能会留下不干净的状态,这可能会导致其他测试失败(用户不会注意到)。

相反,我推荐

  1. --pdb用于在错误时进入 Python 调试器。夹具尚未清理干净,您可以检查文件。
  2. 创建一个允许您禁用清理 tmpdir 的自定义选项。
  3. 创建一个自定义 tmpdir 固定装置,将所有 tmpfile 复制到用户可配置的位置(同样,使用自定义选项)并随后清理 tmpdir。

在任何情况下,不干净的 tmpdir 状态将是用户有意识的决定,并将防止意外的副作用。

于 2016-06-01T08:41:00.090 回答
2

您可以从实际项目的funcargs轻松检索您的 tmpdir。

在你的情况下:

from _pytest.runner import runtestprotocol

def pytest_runtest_protocol(item, nextitem):
    reports = runtestprotocol(item, nextitem=nextitem)
    for report in reports:
        if report.when == 'call':
            # value will be set to passed or filed
            test_outcome = report.outcome
            # depending on test_outcome value, remove tmpdir
            if test_outcome is "OK for you":
               if 'tmpdir' in item.funcargs:
                  tmpdir = item.funcargs['tmpdir'] #retrieve tmpdir
                  if tmpdir.check(): tmpdir.remove()

return True

对于这个故事, item.funcargs 是一个字典,其中包含传递给我们当前正在检查的测试项目的 {arguments:value}。所以第一步是检查tmpdir确实是实际测试的 arg,然后检索它。最后在删除它之前检查它的存在。

希望这会有所帮助。

编辑:您的 pytest_runtest_protocol(..) 似乎还没有完全初始化该项目。为了确保它是..

只需覆盖 pytest_runtest_teardown(item),一旦运行完成(成功或失败),它就会作用于每个测试项目。尝试添加这样的方法:

def pytest_runtest_teardown(item):
   if item.rep_call.passed:
      if 'tmpdir' in item.funcargs:
         tmpdir = item.funcargs['tmpdir'] #retrieve tmpdir
         if tmpdir.check(): tmpdir.remove()

当然,不要忘记以下(在文档中给出)以轻松访问您的报告。

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call,):
    # execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()
    # set an report attribute for each phase of a call, which can
    # be "setup", "call", "teardown"
    setattr(item, "rep_" + rep.when, rep)
于 2016-06-29T13:06:40.513 回答