Continuing in Python's unittest when an assertion fails

前端 未结 12 1576
感情败类
感情败类 2020-11-27 14:03

EDIT: switched to a better example, and clarified why this is a real problem.

I\'d like to write unit tests in Python that continue executing when an assertion fails

12条回答
  •  甜味超标
    2020-11-27 14:48

    I had a problem with the answer from @Anthony Batchelor because it would have forced me to use try...catch inside my unit tests. Instead, I encapsulated the try...catch logic in an override of the TestCase.assertEqual method. Here is the code:

    import unittest
    import traceback
    
    class AssertionErrorData(object):
    
        def __init__(self, stacktrace, message):
            super(AssertionErrorData, self).__init__()
            self.stacktrace = stacktrace
            self.message = message
    
    class MultipleAssertionFailures(unittest.TestCase):
    
        def __init__(self, *args, **kwargs):
            self.verificationErrors = []
            super(MultipleAssertionFailures, self).__init__( *args, **kwargs )
    
        def tearDown(self):
            super(MultipleAssertionFailures, self).tearDown()
    
            if self.verificationErrors:
                index = 0
                errors = []
    
                for error in self.verificationErrors:
                    index += 1
                    errors.append( "%s\nAssertionError %s: %s" % ( 
                            error.stacktrace, index, error.message ) )
    
                self.fail( '\n\n' + "\n".join( errors ) )
                self.verificationErrors.clear()
    
        def assertEqual(self, goal, results, msg=None):
    
            try:
                super( MultipleAssertionFailures, self ).assertEqual( goal, results, msg )
    
            except unittest.TestCase.failureException as error:
                goodtraces = self._goodStackTraces()
                self.verificationErrors.append( 
                        AssertionErrorData( "\n".join( goodtraces[:-2] ), error ) )
    
        def _goodStackTraces(self):
            """
                Get only the relevant part of stacktrace.
            """
            stop = False
            found = False
            goodtraces = []
    
            # stacktrace = traceback.format_exc()
            # stacktrace = traceback.format_stack()
            stacktrace = traceback.extract_stack()
    
            # https://stackoverflow.com/questions/54499367/how-to-correctly-override-testcase
            for stack in stacktrace:
                filename = stack.filename
    
                if found and not stop and \
                        not filename.find( 'lib' ) < filename.find( 'unittest' ):
                    stop = True
    
                if not found and filename.find( 'lib' ) < filename.find( 'unittest' ):
                    found = True
    
                if stop and found:
                    stackline = '  File "%s", line %s, in %s\n    %s' % ( 
                            stack.filename, stack.lineno, stack.name, stack.line )
                    goodtraces.append( stackline )
    
            return goodtraces
    
    # class DummyTestCase(unittest.TestCase):
    class DummyTestCase(MultipleAssertionFailures):
    
        def setUp(self):
            self.maxDiff = None
            super(DummyTestCase, self).setUp()
    
        def tearDown(self):
            super(DummyTestCase, self).tearDown()
    
        def test_function_name(self):
            self.assertEqual( "var", "bar" )
            self.assertEqual( "1937", "511" )
    
    if __name__ == '__main__':
        unittest.main()
    

    Result output:

    F
    ======================================================================
    FAIL: test_function_name (__main__.DummyTestCase)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "D:\User\Downloads\test.py", line 77, in tearDown
        super(DummyTestCase, self).tearDown()
      File "D:\User\Downloads\test.py", line 29, in tearDown
        self.fail( '\n\n' + "\n\n".join( errors ) )
    AssertionError: 
    
      File "D:\User\Downloads\test.py", line 80, in test_function_name
        self.assertEqual( "var", "bar" )
    AssertionError 1: 'var' != 'bar'
    - var
    ? ^
    + bar
    ? ^
     : 
    
      File "D:\User\Downloads\test.py", line 81, in test_function_name
        self.assertEqual( "1937", "511" )
    AssertionError 2: '1937' != '511'
    - 1937
    + 511
     : 
    

    More alternative solutions for the correct stacktrace capture could be posted on How to correctly override TestCase.assertEqual(), producing the right stacktrace?

提交回复
热议问题