11

I have looked at the other related questions here but have not found my answer. I would like to simplify the output of my Python (2.7) unittests. Trying sys.tracebacklimit = 0 did not work.

Here is my code snippet (the real code generates lots of similar tests):

#!/usr/bin/python -E
import unittest
import os
import sys

class TestSequense(unittest.TestCase):
    pass

def test_dir_exists(dir):
    def test(self):
        self.assertTrue(os.path.isdir(dir),"ERROR: " + dir + " is not a directory")
    return test

if __name__ == '__main__':
    test = test_dir_exists("/something/not/set/correctly")
    setattr(TestSequense, "test_path",  test)
    #TODO trying remove unnecessary traceback info... still not working
    sys.tracebacklimit = 0
    unittest.main()

The output is currently:

F
======================================================================
FAIL: test_path (__main__.TestSequense)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./simple_unittest.py", line 11, in test
    self.assertTrue(os.path.isdir(dir),"ERROR: " + dir + " is not a directory")
AssertionError: ERROR: /something/not/set/correctly is not a directory

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

I would like it to look like this:

F
======================================================================
FAIL: test_path (__main__.TestSequense)
----------------------------------------------------------------------
AssertionError: ERROR: /something/not/set/correctly is not a directory

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

Is this possible without parsing the output? The Traceback gives me no useful information and I am running 1000's of tests.

Thanks in advance!

internetscooter
  • 251
  • 2
  • 8
  • 1
    Not a solution, but the traceback tells you which assertion is throwing the error. It lets you go straight to the line where the assertion failure occurred, rather than having to think about which assertion would have generated that message. Especially if you don't use assertion messages or multiple assertions have the same message, this is really helpful. You might regret removing it. – user2357112 Nov 05 '15 at 22:32
  • thanks but I always know the line it came from - first iteration of the test suite there is only one line it can come from. I'll add a verbose option if it get more complicated – internetscooter Nov 11 '15 at 03:05

3 Answers3

6

unittest has a mechanism for hiding the contents of the TestCase.assert* methods in the traceback, as those really don't contain any useful information for failures. It looks for __unittest in the frame's globals. You can hide an entire module from the tracebacks by putting __unittest = True at the top of the module.

Subhaneil Lahiri
  • 408
  • 3
  • 10
  • 1
    Simplified version of this answer: put `__unittest = True` at the top of your file that contains your test cases. – connorbode May 15 '20 at 14:09
5

I'm not sure if it's possible with vanilla unittest module. But you should take a look at py.test, with it you can configure the amount of information shown in a traceback with the --tb switch.

Probably you are interested in

py.test --tb=line    # only one line per failure

See this page for a full list of options.

memoselyk
  • 3,993
  • 1
  • 17
  • 28
1

The trick is to catch the exception, strip out the bits that aren't needed and throw it again...

Based on this answer - the following code works...

#!/usr/bin/python -E
import unittest
import os
import sys

class TestSequense(unittest.TestCase):
    pass

def test_dir_exists(dir):
    def test(self):
       try:
           self.assertTrue(os.path.isdir(dir),"ERROR: " + dir + " is not a directory")
       except:
           # Remove traceback info as we don't need it
           unittest_exception = sys.exc_info()
           raise unittest_exception[0], unittest_exception[1], unittest_exception[2].tb_next
    return test

if __name__ == '__main__':
    test = test_dir_exists("/something/not/set/correctly")
    setattr(TestSequense, "test_path",  test)
    unittest.main()

And generates the following...

./simple_unittest.py
F
======================================================================
FAIL: test_path (__main__.TestSequense)
----------------------------------------------------------------------
AssertionError: ERROR: /something/not/set/correctly is not a directory

----------------------------------------------------------------------
Ran 1 test in 0.000s
Community
  • 1
  • 1
internetscooter
  • 251
  • 2
  • 8