web-dev-qa-db-ja.com

pytestテストケースが失敗したことを検出する方法は?

Seleniumでpytestを使用してWebサイトを自動化しています。テストケースが失敗した場合にのみスクリーンショットを撮りたいです。私は以前に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()失敗がない場合にのみ実行されます

14
pr4bh4sh

あなたによると post stackoverflowで、私は私の頭の中にあることを共有できます、それが役立つことを願っています:ウィンク:あなたがしようとしているのは標準を処理することですAssertionErrorassertによって発生する可能性のある例外)キーワード、または nittest.TestCase に実装されているアサーションメソッド、またはカスタム例外を発生させるカスタムアサーションメソッド。これを行うには3つの方法があります。

  1. try-except-finally構文を使用します。いくつかの基本的な例:

    try:
        Assert.fail("failed test")
    except AssertionError:
        get_screenshot()
        raise
    
  2. または、コンテキストマネージャーとしてwithステートメントを使用します。

    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")
    
12
Alex-Bogdanov

いくつかの苦労の後、最終的にこれは私のために働いた。

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の例 および これを簡単にする(しない)スレッド

5
JJC

これが私たちのやり方です、注意__ multicall __ドキュメントが非常に少なく、読んだことを覚えています__ multicall __は非推奨になります。これを塩のピンチで使用し、置き換えてみてください__ multicall __ with 'item、call'例のとおり。

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
1
Sanju
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))
0
Xiang Zhang