【问题标题】:Automatic screenshots when test fail by Selenium Webdriver in PythonPython 中 Selenium Webdriver 测试失败时的自动截图
【发布时间】:2012-08-15 00:38:53
【问题描述】:

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

【问题讨论】:

    标签: python selenium webdriver screenshot


    【解决方案1】:

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

    【讨论】:

    • 谢谢!我认为这是使用 try:except 的正确方法,现在我看到了这个
    • 这很好用,但是以这种方式吞下异常会阻止单元测试工具报告错误。如果在包含多个测试的单元测试类中使用此代码,则值得在 except 块的末尾添加“raise e”。
    【解决方案2】:

    另一种方法是将以下内容添加到您的 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):
            ...
    

    【讨论】:

      【解决方案3】:

      供将来参考/这里的人是一个适用于 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/

      【讨论】:

      • 不通过addCleanup()添加screen_shot方法,也可以将逻辑放在tearDown()中
      【解决方案4】:

      这是一个使用装饰器的解决方案,该装饰器将每个方法包装在以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)
      

      【讨论】:

        【解决方案5】:

        您可以开始探索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')
        

        【讨论】:

          【解决方案6】:
          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))
          

          【讨论】:

          • 你能解释一下为什么上面的代码有效吗?
          【解决方案7】:

          对于我的类中的 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)
          

          【讨论】:

            【解决方案8】:

            帮我解决这个问题:

            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-01-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-29
              • 1970-01-01
              • 2012-09-07
              相关资源
              最近更新 更多