admin管理员组

文章数量:1399474

I would like to change via command-line the logging level of my unit tests - I am talking of the logging level, which means the amount of info that can help me debugging a module that I am testing (not included here).

I am fixing an old project that uses unittest.TextTestRunner. Please note: in python2, I could use the self._resultForDoCleanups attribute, but that's now gone. I am running python 3.6.

This is the module-specific file containing the testCases, save it as testCases.py (will be imported by the caller):

#!/usr/bin/env python3

# used to manage testing environment
import unittest
import os
import sys

import logging
logger = logging.getLogger(__name__)
# One can change logging level here.
logger.setLevel(os.environ.get('LOG_LEVEL', logging.INFO))
 
class myTestCase(unittest.TestCase):
    # ########## ##############################
    # TEST LP000 ##############################
    def test_LP000(self):
        # does not work (VL not accessible in this scope)
        # print(VL)
        logger.info('For INFO message')
        logger.debug('For DEBUG message')
        logger.warning('For WARNING message')
        logger.error('For ERROR message')
        logger.critical('For CRITICAL message')

        #old scheme in python2 : I could set VL as a function of
        # the runner verbosity
        #if hasattr(self._resultForDoCleanups, 'dots'):
        #    if (self._resultForDoCleanups.dots):
        #        VL = 1
        #if hasattr(self._resultForDoCleanups, 'showAll'):
        #    if (self._resultForDoCleanups.showAll):
        #        VL = 2

        # so I hard-code it here, but I wish I could get it from
        # the caller module
        VL = 1 
        libertyFileName = 'Hello_guys'
        # Next example shall be replaced by more complex evaluations
        csvFile5 = os.path.join('.', 'INPUT', libertyFileName)
        if VL:
            # print something for any verbose level
            print( 'P2C | Test file      : ', csvFile5)
        if VL > 1:
            # print something only for higher verbosity
            print( 'Even more verbosity added if I found something in the file')

This is the caller module:

#!/usr/bin/env python3
import unittest
import argparse
import os
import sys
sys.path.append('.')
import testCases

if __name__ == '__main__':
    # Set verbose to 1 if you want to have details on what is done
    # (Or add "-v" when calling this file in terminal)
    VL = 0

    ############################
    ## ARGUMENT PARSING PHASE ##
    ############################
    parser = argparse.ArgumentParser(description="An interactive way to invoke unit tests")

    parser.add_argument("-v", "--verbose",
        help="Verbosity level",
        action="store", default=0)

    args = parser.parse_args()
    if args.verbose:
        VL = int(args.verbose)

    print( "setup phase completed")
    print( "Requested VL : " + str(VL))
    d = testCases.myTestCase('test_LP000')
    o = unittest.TextTestRunner(verbosity=VL)
    s = o.run(d)
    print( 'errors   = ' +str(len(s.errors)))        
    print( 'failures = ' +str(len(s.failures)))
    print( 'skipped  = ' +str(len(s.skipped)))
    print( 'testsRun = ' +str(s.testsRun))

This is the current output I get:

gre066958/pymem 717 >>./bin/minimumTest.py
setup phase completed
Requested VL : 0
For WARNING message
For ERROR message
For CRITICAL message
P2C | Test file      :  ./INPUT/Hello_guys
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
errors   = 0
failures = 0
skipped  = 0
testsRun = 1
gre066958/pymem 718 >>./bin/minimumTest.py -v 7
setup phase completed
Requested VL : 7
test_LP000 (testCases.myTestCase) ... For WARNING message
For ERROR message
For CRITICAL message
P2C | Test file      :  ./INPUT/Hello_guys
ok

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

OK
errors   = 0
failures = 0
skipped  = 0
testsRun = 1

As you can see, the -v argument is parsed and controls the verbosity of the TextTestRunner : at an higher verbosity level, there is an output line containing the testCase name, an output line containing 'ok' and a blank line. Basically the TextTestRunner has the three levels 0, 1 and 2 where verbosity is either null, a single dot per testcase or a bit more info about the testCase.

Now I would rather be able to increase the logging level - for the specific test cases that fail: Basically I would love to run everything at low verbosity, capturing only which unit tests fail, then rerun those tests that fail at higher verbosity (I can select the testcases via command-line, not included in my snippet here).

All I can find is to modify manually the hard-coded value of VL into the given failing tests... that works, but maybe I am missing something more pythonic in the global unit testing strategy using the unittest module? How do you write your code including increasing levels of logging - I am not really used to the logging module, in any case it seems to me that I will be unable to increase logging level if I cannot access the verbosity level of the runner...

Any hints or comments welcome.

本文标签: python 3xControlling from the top the verbositylogging level in unittestTextTestRunnerStack Overflow