12

Python の unittest2 フレームワークでいくつかのクラスベースの単体テストを実行しています。save_screenshot()便利なメソッドを持つ Selenium WebDriver を使用しています。テストが失敗するたびに、tearDown() でスクリーンショットを取得して、テストが失敗した理由のデバッグに費やす時間を短縮したいと考えています。

ただし、テストが失敗した場合にのみコードを実行する方法が見つかりません。tearDown()テストが成功したかどうかに関係なく呼び出され、成功したテストの何百ものブラウザーのスクリーンショットでファイルシステムを混乱させたくありません。

これにどのようにアプローチしますか?

4

5 に答える 5

8

解決策が見つかりました-オーバーライドできますfailureException

@property
def failureException(self):
    class MyFailureException(AssertionError):
        def __init__(self_, *args, **kwargs):
            self.b.save_screenshot('%s.png' % self.id())
            return super(MyFailureException, self_).__init__(*args, **kwargs)
    MyFailureException.__name__ = AssertionError.__name__
    return MyFailureException

これは信じられないほどハッキーなようですが、これまでのところうまくいくようです。

于 2012-09-06T00:25:39.143 に答える
3

これは@craigds answerと同様のアプローチですが、ディレクトリのサポートと Python 3 との互換性が向上しています。

@property
def failureException(self):
    class MyFailureException(AssertionError):
        def __init__(self_, *args, **kwargs):
            screenshot_dir = 'reports/screenshots'
            if not os.path.exists(screenshot_dir):
                os.makedirs(screenshot_dir)
            self.driver.save_screenshot('{0}/{1}.png'.format(screenshot_dir, self.id()))
            return super(MyFailureException, self_).__init__(*args, **kwargs)
    MyFailureException.__name__ = AssertionError.__name__
    return MyFailureException

これは実際にこのブログで発見されました。

私はそれをさらに拡張しましたargparse

parser.add_argument("-r", "--reports-dir", action="store",   dest="dir",      help="Directory to save screenshots.", default="reports")     

したがって、ディレクトリは、システム変数または渡された引数によって動的に指定できます。

screenshot_dir = os.environ.get('REPORTS_DIR', self.args.dir) + '/screenshots'

これは、基本クラスのように、すべてのスクリプトを実行するための追加のラッパーがある場合に特に便利です。

于 2015-05-16T21:07:54.623 に答える
2

sys.exc_info()テストが失敗したかどうかに関する終了情報を提供する必要があります。だから、このようなもの:

def tearDown(self):
    if sys.exc_info()[0]:
        path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../failures', self.driver.browser)
        if not os.path.exists(path):
            try:
                os.makedirs(path)
            except Exception:
                # Since this might not be thread safe
                pass
        filename = '%s.%s.png' % (self.__class__.__name__, self._testMethodName)
        file_path = os.path.join(path, filename)
        self.driver.get_screenshot_as_file(file_path)
于 2013-05-31T15:23:02.173 に答える
1

各テストの周りにデコレータを使用します。

新しいテストを装飾することを覚えておく、または既存のテストの束に戻って装飾することを避けるための最も安全な方法は、メタクラスを使用してすべてのテスト関数をラップすることです。クラスのすべてのメソッドをラップする方法は? 回答は、必要なものの基本を提供します。

おそらく、テストだけにラップダウンされた関数をフィルタリングする必要があります。たとえば、次のようになります。

class ScreenshotMetaClass(type):
    """Wraps all tests with screenshot_on_error"""
    def __new__(meta, classname, bases, classDict):
        newClassDict = {}
        for attributeName, attribute in classDict.items():
            if type(attribute) == FunctionType and 'test' in attributeName.lower():
                # replace the function with a wrapped version
                attribute = screenshot_on_error(attribute)
            newClassDict[attributeName] = attribute
        return type.__new__(meta, classname, bases, newClassDict)
于 2013-05-21T21:59:34.150 に答える