1

I have many print statements within my unittest test methods and I would like to be able to see them printed out underneath each "ok" row in the console output. Does anyone have a way to do this? Thank you.

test_01...ok
This is a print statement for test 1
test_02...ok
This is a print statement for test 2
test_03...ok
This is a print statement for test 3
steveb
  • 5,382
  • 2
  • 27
  • 36
SAB15
  • 41
  • 1
  • 4

1 Answers1

2

The short answer is verbosity, runner = unittest.TextTestRunner(verbosity=2).

The longer answer, if you want to store the output streams is more complicated. std.io and std.err are managed by the OS and they are flushed differently when connected to the terminal than when redirected to a file.

Some examples, Unit under test (filename testablepython.py)

def run():
    print(f"{__name__} unit print")
    return(True)

test code body (filename test/test_tests.py)

import unittest
import logging
import testablepython as unit
import os
import sys
# import pandas as pd

class Test_ClassOne(unittest.TestCase):
    def test_A(self):
        self.assertTrue(unit.run())
        logging.info('log: passed test_one'

    def test_B(self):
        self.assertFalse(not unit.run())
        logging.info('log: passed test_falseisnottrue')

class Test_ClassTwo(unittest.TestCase):
    def test_three(self):
        logging.info(f"log: in test_three, does not call unit")
        self.assertTrue(True)

the main block that works to console but not on redirect:

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    runner = unittest.TextTestRunner(verbosity=2)
    unittest.main(testRunner=runner)

console output:

$python -m test.test_tests
test_A (__main__.Test_ClassOne) ... testablepython unit print
INFO:root:log: passed test_one
ok
test_B (__main__.Test_ClassOne) ... testablepython unit print
INFO:root:log: passed test_falseisnottrue
ok
test_three (__main__.Test_ClassTwo) ... INFO:root:log: output three ['fred', 'alaska', 'baker']
ok

----------------------------------------------------------------------
Ran 3 tests in 0.003s

OK
$ 

Note the lack of a newline between the test fixture and the print() code from the unit under test, no flush. On redirect the streams are un-mixed, std.err first then std.io.

$ python -m test.test_tests &> temp.txt
$ cat temp.txt
test_A (__main__.Test_ClassOne) ... INFO:root:log: passed test_one
ok
test_B (__main__.Test_ClassOne) ... INFO:root:log: passed test_falseisnottrue
ok
test_three (__main__.Test_ClassTwo) ... INFO:root:log: output three ['fred', 'alaska', 'baker']
ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK
testablepython unit print
testablepython unit print

The solution seems to be to reconfigure the outputs to force them to flush during operation. solution:

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)

    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
    sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)

    runner = unittest.TextTestRunner( verbosity=2)
    unittest.main(testRunner=runner)

Note the lack of a newline between the test fixture and the print() code from the unit under tesNow we get the desired redirected output:

$ python -m test.test_tests &> temp.txt
$ cat temp.txt
test_A (__main__.Test_ClassOne) ... testablepython unit print
INFO:root:log: passed test_one
ok
test_B (__main__.Test_ClassOne) ... testablepython unit print
INFO:root:log: passed test_falseisnottrue
ok
test_three (__main__.Test_ClassTwo) ... INFO:root:log: output three ['fred', 'alaska', 'baker']
ok

----------------------------------------------------------------------
Ran 3 tests in 0.002s

Or we can see both by calling unittest with a tee: python -m test.test_tests 2>&1 | tee tmp.txt

steveb
  • 5,382
  • 2
  • 27
  • 36
PeterK
  • 1,185
  • 1
  • 9
  • 23