30

如果我的 webdriver 测试失败(任何异常或断言错误),我想自动捕获屏幕截图。我正在使用 Python unittest 和 Selenium Webdriver。有没有人有解决这个问题的方法?

4

8 回答 8

28

在 Firefox 中做一些 webdriver 的东西......将任何异常的屏幕截图保存到过时的图像文件中:

from datetime import datetime
from selenium import webdriver

browser = webdriver.Firefox()

try:
    # do some webdriver stuff here
except Exception as e:
    print e
    now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
    browser.get_screenshot_as_file('screenshot-%s.png' % now)
于 2012-08-19T13:12:01.320 回答
11

另一种方法是将以下内容添加到您的tearDown方法中:

if sys.exc_info()[0]:
    test_method_name = self._testMethodName
    self.driver.save_screenshot("Screenshots/%s.png" % test_method_name)

这将假设一个像这样的测试类:

class SeleniumTest(unittest2.TestCase):
    ...

    def tearDown(self):
        if sys.exc_info()[0]:
            test_method_name = self._testMethodName
            self.driver.save_screenshot("Screenshots/%s.png" % test_method_name)
        super(SeleniumTest, self).tearDown()

    def test_1(self):
        ...

    def test_2(self):
        ...
于 2015-12-16T19:42:03.547 回答
9

供未来参考/这里的人是一个在 Python3 中工作的解决方案,它既适用于异常,也适用于失败的断言。

(基于https://stackoverflow.com/a/23176373/9427691

#!/usr/bin/env python

"""
An Example code to show the set-up with screen-shot on exception.
"""

import unittest
from selenium import webdriver


class TestDemo(unittest.TestCase):
    """An Example test Case, to show off the set-up of a screen-shot on exception."""

    def setUp(self):
        """Set up the Firefox Browser and the Tear Down."""
        self.driver = webdriver.Firefox()
        self.driver.delete_all_cookies()
        # NOTE: In addCleanup, the first in, is executed last.
        self.addCleanup(self.driver.quit)
        self.addCleanup(self.screen_shot)
        self.driver.implicitly_wait(5)

    def screen_shot(self):
        """Take a Screen-shot of the drive homepage, when it Failed."""
        for method, error in self._outcome.errors:
            if error:
                self.driver.get_screenshot_as_file("screenshot" + self.id() + ".png")

    def test_demo(self):
        """A test case that fails because of missing element."""
        self.driver.get("http://www.google.com")
        self.driver.find_element_by_css_selector("div.that-does-not-exist")

    def test_demo2(self):
        """A test case that fails because assert."""
        self.driver.get("https://stackoverflow.com")
        self.assertEqual(True, False)

if __name__ == '__main__':
    unittest.main(verbosity=2)

self._outcome.errors

仅限 Python3,因此适用于 Python2

self._outcomeForDoCleanups.errors

反而。

对于那些只想要异常屏幕截图的人。你应该看看这个链接:http ://blog.likewise.org/2015/01/automatically-capture-browser-screenshots-after-failed-python-ghostdriver-tests/

于 2018-03-15T15:33:14.870 回答
5

这是一个使用装饰器的解决方案,该装饰器将类上的每个方法包装起来,该类test_以包装器开头,如果方法引发和异常,该包装器会截取屏幕截图。用于告诉装饰器browser_attr如何获取网络浏览器(驱动程序)。

from functools import partialmethod


def sreenshotOnFail(browser_attr='browser'):
    def decorator(cls):
        def with_screen_shot(self, fn, *args, **kwargs):
            """Take a Screen-shot of the drive page, when a function fails."""
            try:
                return fn(self, *args, **kwargs)
            except Exception:
                # This will only be reached if the test fails
                browser = getattr(self, browser_attr)
                filename = 'screenshot-%s.png' % fn.__name__
                browser.get_screenshot_as_file(filename)
                print('Screenshot saved as %s' % filename)
                raise

        for attr, fn in cls.__dict__.items():
            if attr[:5] == 'test_' and callable(fn):
                setattr(cls, attr, partialmethod(with_screen_shot, fn))

        return cls
    return decorator


@sreenshotOnFail()
class TestDemo(unittest.TestCase):
    def setUp(self):
        """Set up the Firefox Browser and the Tear Down."""
        self.browser = webdriver.Firefox()

    def test_demo2(self):
        """A test case that fails because assert."""
        self.driver.get("https://stackoverflow.com")
        self.assertEqual(True, False)
于 2018-04-29T16:50:31.480 回答
2

您可以开始探索self._outcome.errors[1]在哪里可以找到有关错误的信息。
即下面的代码仅适用于断言错误

 def tearDown(self):
        if self._outcome.errors[1][1] and hasattr(self._outcome.errors[1][1][1], 'actual'):
            self.driver.save_screenshot(self._testMethodName + '.png')
于 2018-12-12T08:40:05.923 回答
1
try:
   page2.fill_up_company_info()
except Exception as e:
   with pytest.raises(WebDriverException):
            pytest.fail( f"{e} for error message",       
allure.attach(self.driver.get_screenshot_as_png(),name="screenshot",attachment_type=AttachmentType.PNG))
于 2021-04-08T08:47:05.003 回答
0

对于我的类中的 Django 2.2.2(使用 unittest)进行硒测试,它继承自 StaticLiveServerTestCase,我已经覆盖了 _feedErrorsToResult 方法。此外,这种方法提供了一种棘手的方法来了解被调用方法的名称,以便进行方便的屏幕截图调查。

@classmethod
def _feedErrorsToResult(cls, result, errors):
    """
    Overriding private method at %library root%/Lib/unittest/case.py
    so you can take screenshot with any failed test and find name of the method
    """
    if SELENIUM_TAKE_SCREENSHOTS:
        for test, exc_info in errors:
            if exc_info is not None:
                now = datetime.now().strftime('%y-%m-%d_%H-%M-%S')
                test_name = exc_info[2].tb_frame.f_locals["test_case"]._testMethodName
                # noinspection PyUnresolvedReferences
                cls.selenium.get_screenshot_as_file('%s/%s-%s-%s.png' % (SELENIUM_SCREENSHOTS_PATH, cls.__name__, test_name, now))
    # noinspection PyUnresolvedReferences
    super()._feedErrorsToResult(cls, result, errors)
于 2019-10-05T18:19:44.107 回答
-2

对我来说帮助这个解决方案:

def teardown_method(self, method):
    """Driver elimination"""
    if sys.exc_info():
        allure.attach('screenshot', self.driver.get_screenshot_as_png(), type=AttachmentType.PNG)
    self.driver.quit()
    pass
于 2016-04-04T03:10:54.943 回答