Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python unittest, do something only if test fails

When using the unittest library from python 3 I would like to do some actions only if a test fails (but this should be on a class level so I don't have to write it for each test). For example when using behave there was something like:

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

Is there something similar for the unittestlibrary and if not, what would be the easiest approach to do something similar?

like image 210
skamsie Avatar asked Jun 04 '15 15:06

skamsie


2 Answers

I am trying to do something similarly recently and I found a way out:

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

If you want to do different work according to different test case class, you can achieve it like this:

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)
like image 179
WKPlus Avatar answered Oct 18 '22 06:10

WKPlus


You could try to do it with decorator:

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

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

And in unit test:

@ExceptionHandler  
def test_fail(self):
    self.assert_false(True)
like image 23
dexiu Avatar answered Oct 18 '22 04:10

dexiu