开发者

Run Python unittest so that nothing is printed if successful, only AssertionError() if fails

I have a test module in the standard unittest format

class my_test(unittest.TestCase):

    def test_1(self):
        [tests]

    def test_2(self):
        [tests]
  etc....

My company has a proprietary test harness that will execute my module as a command line script, and which will catch any errors raised by my module, but requires that my module be mute if successful.

So, I am trying to find a way to run my test module naked, so that if all my tests pass then nothing is printed to the screen, and if a test fails with an AssertionError, that error gets piped through the standard Python error stack (just like any other error would in a normal Python script.)

The docs advocate using the unittest.main() function to run all the tests in a given module like

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

The problem is that this wraps the test results in unittest's harness, so that even if all tests are successful, it still prints some fluff to the screen, and if there is an error, it's not simply dumped as a usual python error, but also dressed in the harness.

I've tried redirecting the output to an alternate stream using

with open('.LOG','a') as logf:
    suite = unittest.TestLoader().loadTestsFromTestCase(my_test)
    unittest.TextTestRunner(stream = logf).run(suite)

The problem here is that EVERYTHING gets piped to the log file (including all notice of errors). So when my companies harness runs the module, it complete's successfully because, as far as it can tell, no errors were raised (because they were all piped to the log file).

Any suggestions on how I can construct a test runner that suppresses all the fluff, and pipes errors through the normal Python error stack? As always, if you think there is a better way to approach this problem, please let me know.

EDIT:

Here is what I ended up using to resolve this. First, I added a "get_test_names()" method to my test class:

class my_test(unittest.TestCase):
  etc....
    @staticmethod
    def get_test_names():
        """Return the names of all the test methods for this class."""
        test_names = [ member[0] for memeber in inspect.getmembers(my_test)
                       if 'test_' in member[0] ]

Then I replaced my call to unittest.main() with the following:

# Unittest catches all errors raised by the test cases, and returns them as 
# formatted strings i开发者_如何学编程nside a TestResult object. In order for the test 
# harness to catch these errors they need to be re-raised, and so I am defining 
# this CompareError class to do that. 
# For each code error, a CompareError will be raised, with the original error 
# stack as the argument. For test failures (i.e. assertion errors) an 
# AssertionError is raised.
class CompareError(Exception):
    def __init__(self,err):
        self.err = err
    def __str__(self):
        return repr(self.err)

# Collect all tests into a TestSuite()
all_tests = ut.TestSuite()
for test in my_test.get_test_names():
    all_tests.addTest(my_test(test))
# Define a TestResult object and run tests
results = ut.TestResult()
all_tests.run(results)
# Re-raise any script errors
for error in results.errors:
    raise CompareError(error[1])
# Re-raise any test failures 
for failure in results.failures:
    raise AssertionError(failure[1])


I came up with this. If you are able to change the command line you might remove the internal io redirection.

import sys, inspect, traceback

# redirect stdout,
# can be replaced by testharness.py > /dev/null at console
class devnull():
    def write(self, data):
        pass

f = devnull()
orig_stdout = sys.stdout
sys.stdout = f

class TestCase():
    def test_1(self):
        print 'test_1'

    def test_2(self):
        raise AssertionError, 'test_2'

    def test_3(self):
        print 'test_3'


if __name__ == "__main__":
    testcase = TestCase()
    testnames =  [ t[0] for t in inspect.getmembers(TestCase)
                        if t[0].startswith('test_') ]

    for testname in testnames:
        try:
            getattr(testcase, testname)()
        except AssertionError, e:
            print >> sys.stderr, traceback.format_exc()

# restore
sys.stdout = orig_stdout
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜