Python unittest,只有在测试失败时才做某事

问题描述 投票:8回答:4

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

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

有什么类似的unittestlibrary,如果没有,什么是最简单的方法来做类似的事情?

python unit-testing
4个回答
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
投票

你可以试着用装饰器来做:

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)

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

-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()
© www.soinside.com 2019 - 2024. All rights reserved.