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

时间:2016-02-29 15:20:33

标签: python selenium 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()仅在没有失败时执行

4 个答案:

答案 0 :(得分:8)

根据你在stackoverflow上的post,我可以分享我的想法,我希望它会有所帮助:wink: 您要做的是处理可由 assert 关键字或unittest.TestCase中实现的任何断言方法引发的标准 AssertionError 异常或者可能是任何引发自定义异常的自定义断言方法。 有三种方法可以做到:

  1. 使用 try-except-finally 构造。一些基本的例子:

    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")
    
         

    here你可以深入了解如何玩它

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

    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")
    

答案 1 :(得分:3)

经过一番努力,最终这对我有用。

在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

请注意"请求"是一个固定的" funcarg" pytest在您的测试环境中提供。你不必自己定义它。

来源:pytest examplesthread on (not) making this easier

答案 2 :(得分:1)

这就是我们这样做的方法,请注意 __ 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

答案 3 :(得分:0)

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))