如何检测 pytest 测试用例何时失败



我正在使用pytest和Selenium来自动化网站。我想仅在测试用例失败时拍摄一些屏幕截图。我以前使用过TestNG,而TestNG使用ITestListner是相当东方的。我们在pytest中有这样的东西吗?

我尝试使用 teardown_method() 来实现这一点但是当测试用例失败时,此方法不会执行。

import sys
from unittestzero import Assert
class TestPY:
    def setup_method(self, method):
        print("in setup method")
        print("executing " + method.__name__)
    def teardown_method(self, method):
        print(".....teardown")
        if sys.exc_info()[0]:
            test_method_name = method
            print test_method_name
    def test_failtest(self):
        Assert.fail("failed test")

teardown_method()仅在没有失败时才执行

根据你在stackoverflow上的帖子,我可以分享我的想法,我希望它会有所帮助:眨眼:您要做的是处理标准的断言错误异常,该异常可以通过 assert 关键字或 unittest 中实现的任何断言方法引发。测试用例或任何引发自定义异常的自定义断言方法。有 3 种方法可以做到这一点:

  1. 使用"尝试-但-最终"构造。一些基本示例:

    try:
        Assert.fail("failed test")
    except AssertionError:
        get_screenshot()
        raise
    
  2. 或者与语句一起使用,作为上下文管理器:

    class TestHandler:
        def __enter__(self):
            #  maybe some set up is expected before assertion method call
            pass
        def __exit__(self, exc_type, exc_val, exc_tb):
            #  catch whether exception was raised
            if isinstance(exc_val, AssertionError):
                get_screenshot()
    
    with TestHandler():
        Assert.fail("failed test")
    

    在这里,您可以更深入地了解如何使用它

  3. 在我看来,最后一个是最优雅的方法。使用装饰器。使用此装饰器,您可以装饰任何测试方法:

    def decorator_screenshot(func):
        def wrapper(*args, **kwargs):
            try:
               func(*args, **kwargs)
            except AssertionError:
               get_screenshot()
               raise
        return wrapper
    
    @decorator_screenshot
    def test_something():
        Assert.fail("failed test")
    

经过一番挣扎,最终这对我有用。

在 conftest.py:

@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    rep = outcome.get_result()
    setattr(item, "rep_" + rep.when, rep)
    return rep
而且,在您的代码中,在夹具中

(例如,在用于测试的拆解夹具中),像这样使用它:

def tear_down(request):
    method_name = request.node.name
    if request.node.rep_call.failed:
        print('test {} failed :('.format(method_name))
        # do more stuff like take a selenium screenshot

请注意,"request"是pytest在测试上下文中提供的固定装置"funcarg"。您不必自己定义它。

来源:pytest 示例和线程(不是)使这更容易。

这就是我们的做法,请注意__multicall__的文档非常少,我记得阅读__multicall__将被弃用,请用一点盐使用它,并尝试按照示例将__multicall__替换为"项目,调用"。

def pytest_runtest_makereport(__multicall__):
    report = __multicall__.execute()
    if report.when == 'call':
        xfail = hasattr(report, 'wasxfail')
        if (report.skipped and xfail) or (report.failed and not xfail):
           try:
              screenshot = APP_DRIVER.take_screen_shot(format="base64")

           except Exception as e:
              LOG.debug("Error saving screenshot !!")
              LOG.debug(e)
    return report
def pytest_runtest_makereport(item, call):
    if call.when == 'call':
        if call.excinfo is not None:
            # if excinfor is not None, indicate that this test item is failed test case
            error("Test Case: {}.{} Failed.".format(item.location[0], item.location[2]))
            error("Error: n{}".format(call.excinfo))

最新更新