Python 对异常执行屏幕截图

Python 对异常执行屏幕截图,python,selenium,testing,Python,Selenium,Testing,嘿,有没有一种方法可以捕获异常的屏幕截图,任何异常。我的“失败”解决方案位于BaseTestCase,unittest.TestCase子类中: class BaseTestCase(unittest.TestCase): @classmethod def setUpClass(cls): """some code""" @property def failureException(self): class MyFailureException(Exception):

嘿,有没有一种方法可以捕获异常的屏幕截图,任何异常。我的“失败”解决方案位于
BaseTestCase
unittest.TestCase
子类中:

class BaseTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""some code"""

@property 
def failureException(self):
    class MyFailureException(Exception):
        def __init__(self_, *args, **kwargs):
            screenshot_dir = '../error_log'
            self.driver.save_screenshot('{0}/{1}.jpeg'.format(screenshot_dir, self.id()))
            return super().__init__(*args, **kwargs)

    MyFailureException.__name__ = Exception.__name__
    return MyFailureException

最初它是
AssertionError
而不是
异常
,但它只会捕获断言错误,我对其他类型的错误更感兴趣

最好将异常日志保存到文件中,而不是截图。有关实践,请检查此代码:

>>> s = [1, 2]
>>> try:
...  s[3]
... except IndexError as e:
...  print(e)
...
list index out of range
如您所见,可以捕获(并打印)错误消息。尝试使用
open()
而不是
print()
将错误消息保存到文件中。下面是一个例子:

s = [1, 2]
try:
    s[3]
except IndexError as e:
    file = open("logfile", "a")  # 'a' means append to file
    file.write(e)
    file.close()
这是解决您的问题的最简单的方法

此外,捕获任何可能发生的异常也是不明智的。最好抓住最有可能发生的2、3个问题。

您正在寻找一个:


如果您的测试用例函数引发异常,您可以使用decorator来捕获

要做到这一点,您首先需要创建一个decorator函数,该函数返回您希望测试用例包装在其中的函数,如下面的示例所示

def screenshot(func):
    def screenshot_exception(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except:
            self.driver.save_screenshot('{0}/{1}.jpeg'.format(screenshot_dir, self.id()))
            raise
    return screenshot_exception
然后,对于您想要获得的屏幕截图的测试用例,您只需要在测试用例上方添加decorator

@screenshot
def test_case_1():
    raise NameError('Test Error')

要在发生错误或故障时拍摄屏幕截图,请检查
拆卸方法中当前是否存在正在处理的异常:

import unittest, sys, exceptions
from selenium import webdriver


class TestCaseBase(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()

    def tearDown(self):
        type, value, traceback = sys.exc_info()
        if type is exceptions.AssertionError :
            self.driver.save_screenshot(r'screenshot-failure.png')
        elif type is exceptions.Exception :
            self.driver.save_screenshot(r'screenshot-error.png')

        self.driver.quit()

class MyTestCase(TestCaseBase):

    def test_should_take_screenshot_on_failure(self):
        self.driver.get("http://stackoverflow.com/")
        self.assertTrue(False)

    def test_should_take_screenshot_on_error(self):
        self.driver.get("http://stackoverflow.com/")
        raise Exception("my exception")


if __name__ == '__main__':
    unittest.main()
您还可以重写方法
TestResult.addError
TestResult.addFailure

import unittest
from selenium import webdriver


class TestCaseBase(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()

    def tearDown(self):
        self.driver.quit()

    def run(self, result=None):
        super(TestCaseBase, self).run(TestResultEx(result, self))


class MyTestCase(TestCaseBase):

    def test_should_take_screenshot_on_failure(self):
        self.driver.get("http://stackoverflow.com/")
        self.assertTrue(False)

    def test_should_take_screenshot_on_error(self):
        self.driver.get("http://stackoverflow.com/")
        raise Exception("my exception")


class TestResultEx(object):

    def __init__(self, result, testcase):
        self.result = result
        self.testcase = testcase

    def __getattr__(self, name):
        return object.__getattribute__(self.result, name)

    def addError(self, test, err):
        self.result.addError(test, err)
        self.testcase.driver.save_screenshot(r'screenshot-error.png')

    def addFailure(self, test, err):
        self.result.addFailure(test, err)
        self.testcase.driver.save_screenshot(r'screenshot-failure.png')


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

我基本上不能把我所有的单独测试都放到try中,除了block,这就像是500行额外的代码。我需要一个类级别的解决方案,最好是一个与上面相同的答案,这是在方法级别,我需要一个测试类级别的解决方案嘿,谢谢,以前有过这个,被要求在类级别上找到解决方案:(正是我要找的。谢谢!
import unittest
from selenium import webdriver


class TestCaseBase(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()

    def tearDown(self):
        self.driver.quit()

    def run(self, result=None):
        super(TestCaseBase, self).run(TestResultEx(result, self))


class MyTestCase(TestCaseBase):

    def test_should_take_screenshot_on_failure(self):
        self.driver.get("http://stackoverflow.com/")
        self.assertTrue(False)

    def test_should_take_screenshot_on_error(self):
        self.driver.get("http://stackoverflow.com/")
        raise Exception("my exception")


class TestResultEx(object):

    def __init__(self, result, testcase):
        self.result = result
        self.testcase = testcase

    def __getattr__(self, name):
        return object.__getattribute__(self.result, name)

    def addError(self, test, err):
        self.result.addError(test, err)
        self.testcase.driver.save_screenshot(r'screenshot-error.png')

    def addFailure(self, test, err):
        self.result.addFailure(test, err)
        self.testcase.driver.save_screenshot(r'screenshot-failure.png')


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