Python unittest,仅在测试失败时执行某些操作

时间:2015-06-04 15:16:02

标签: python unit-testing

当使用python 3中的unittest库时,我只想在测试失败时做一些操作(但这应该在类级别,所以我不必为每个测试编写它)。例如,当使用 behave 时,有类似的东西:

def after_step(context, step):
    if step.status == "failed":
        ...

unittest库是否有类似内容,如果没有,那么做类似的最简单的方法是什么?

4 个答案:

答案 0 :(得分:4)

我最近尝试做类似的事情,我找到了出路:

import unittest

class MyTestResult(unittest.TestResult):
    def addFailure(self, test, err):
        # here you can do what you want to do when a test case fails 
        print('test failed!')
        super(MyTestResult, self).addFailure(test, err)

    def addError(self, test, err):
        # here you can do what you want to do when a test case raises an error
        super(MyTestResult, self).addError(test, err)

class MyUT(unittest.TestCase):
    def test_fail(self):
        self.assertEqual(1, 2, '123')
        self.assertTrue("ABc".isupper())

if __name__ == '__main__':
    unittest.main(testRunner=unittest.TextTestRunner(resultclass=MyTestResult))

如果你想根据不同的测试用例类做不同的工作,你可以这样做:

import unittest

class MyUT(unittest.TestCase):
    class TestResult(unittest.TestResult):
        def addFailure(self, test, err):
            print('do something when test case failed')
            super(MyUT.TestResult, self).addFailure(test, err)
        def addError(self, test, err):
            print('test case error')
            super(MyUT.TestResult, self).addError(test, err)

    def test_fail(self):
        self.assertEqual(1, 2, "1=2")

class MyUT2(unittest.TestCase):
    class TestResult(unittest.TestResult):
        def addFailure(self, test, err):
            print('do something else when test case failed')
            super(MyUT2.TestResult, self).addFailure(test, err)
        def addError(self, test, err):
            print('test case error')
            super(MyUT2.TestResult, self).addError(test, err)

    def test_fail(self):
        self.assertEqual(1, 2, "1=2")

if __name__ == '__main__':
    classes = [MyUT, MyUT2]
    for c in classes:
        suite = unittest.TestLoader().loadTestsFromTestCase(c)
        unittest.TextTestRunner(resultclass=c.TestResult).run(suite)

答案 1 :(得分:1)

您可以尝试使用装饰器:

class ExceptionHandler(object):
def __init__(self, f):
    self.f = f

def __call__(self, *args, **kwargs):
    try:
        self.f(*args, **kwargs)
    except:
        print('do smth')

在单元测试中:

@ExceptionHandler  
def test_fail(self):
    self.assert_false(True)

答案 2 :(得分:0)

您可以对这些很酷的东西。通过调用原始设置的自定义覆盖默认异常处理程序,并设置自定义属性:

import sys
import unittest
has_failures = []

class IntegrationTests(unittest.TestCase):
    old_failureException = unittest.TestCase.failureException

    @property
    def failureException(self):
        has_failures.append('fail')
        return self.old_failureException

    def setUp(self):
        sys.stderr.write('Setup for %s\n' % self._testMethodName)

        if has_failures:
            self.skipTest("An test has failed, skipping everything else!")

    def test_thing1(self):
        self.assertEqual(1, 2)

    def test_thing2(self):
        pass

def load_tests(loader, standard_tests, pattern):
    suite = unittest.TestSuite()
    suite.addTest( IntegrationTests( 'test_thing1' ) )
    suite.addTest( IntegrationTests( 'test_thing2' ) )
    return suite

# Comment this to run individual Unit Tests
load_tests = None

if __name__ == "__main__":
    unittest.main(verbosity=3)

结果:

test_thing1 (__main__.IntegrationTests) ... Setup for test_thing1
FAIL
test_thing2 (__main__.IntegrationTests) ... Setup for test_thing2
skipped 'An test has failed, skipping everything else!'

======================================================================
FAIL: test_thing1 (__main__.IntegrationTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:\User\Downloads\text.py", line 27, in test_thing1
    self.assertEqual(1, 2)
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 2 tests in 0.003s

FAILED (failures=1, skipped=1)

参考文献:

  1. Getting Python's unittest results in a tearDown() method
  2. if condition in setUp() ignore test
  3. How do you generate dynamic (parameterized) unit tests in python?
  4. How to get currently running testcase name from testsuite in unittest

答案 3 :(得分:-1)

使用私有变量不是很好,但我还没有找到其他方法来访问跟踪测试结果的对象。

import unittest

class TmpTest(unittest.TestCase):

    def tearDown(self):
        result = self._resultForDoCleanups
        if not result.wasSuccessful():
            print "*** test failed"

    def testFoo(self):
        self.assertEqual(2, 2)

if "__main__" == __name__:
    unittest.main()
相关问题