Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I remove CLI arguments using argparse so unittest will accept arg list

I'd like to pass my own arguments into files that are setup for unittest. So calling it from the command line like this should work:

python Test.py --c keith.ini SomeTests.test_one

Currently I'm running into two issues.

1) Arg parse doesn't allow unknown arguments

usage: Test.py [-h] [--c CONFILE] Test.py: error: unrecognized arguments: SomeTests.test_one

2) Unit test doesn't allow unknown arguments. So --c fileName is not accepted by unittest and returns:

AttributeError: 'module' object has no attribute 'keith'

So the idea is to collect my arguments and remove them before calling unittest runner.

import unittest
import argparse

myArgs = None

def getArgs( allArgs ):
    parser = argparse.ArgumentParser( )
    parser.add_argument('--c', dest='conFile', type=str, default=None, help='Config file')
    args = parser.parse_args()

    if ( args.conFile == None ):
        parser.print_help()

    return args


class SomeTests(unittest.TestCase):
    def test_one(self):
        theTest( 'keith' )

    def test_two(self):
        otherTest( 'keith' )

if __name__ == '__main__':
    myArgs = getArgs( sys.argv )
    print 'Config File: ' + myArgs.conFile
    unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))

Interesting I just found parse_known_args() so I changed the parse line to:

args = parser.parse_known_args(['--c']). 

I thought this would solve my issue and give me something to pass to unittest. Unfortunately I get:

Test.py: error: argument --c: expected one argument. 

Shouldn't this work?

like image 545
Keith Avatar asked Sep 02 '25 10:09

Keith


1 Answers

OK took a bit of effort but figured it out. This is totally possible. The documentation for argparse is not correct. The function parse_known_args() should not include a list of known arguments. Also argparse removes arg[0] which is important to return so other commands see a valid argument list. I'd consider this removal a bug. I have included the final example code.

import unittest
import argparse
import sys

myArgs = None

def getArgs( allArgs ):
    parser = argparse.ArgumentParser( )
    parser.add_argument('--c', dest='conFile', type=str, default=None, help='Configuration file. (Required)')
    args, addArgs = parser.parse_known_args( )

    if ( args.conFile == None ):
        parser.print_help()
        sys.exit(2)

    # argparse strips argv[0] so prepend it
    return args, [ sys.argv[0]] + addArgs

def verify( expected, actual ):
    assert expected == actual, 'Test Failed: '

# Reusable Test
def theTest( exp ):
    print 'myargs: ' + str( myArgs )
    verify( exp, 'keith' )

def otherTest( exp ):
    theTest( exp )

class SomeTests(unittest.TestCase):
    def test_one(self):
        theTest( 'keith' )

    def test_two(self):
        otherTest( 'keith2' )

if __name__ == '__main__':
    myArgs, addArgs = getArgs( sys.argv )
    unittest.main( argv=addArgs, testRunner = unittest.TextTestRunner(verbosity=2))

Once you save this to a file you can call it like the examples below and it will all work.

python Test.py                     # Requires config file
python Test.py --c keith.ini       # Runs all tests
python Test.py --c keith.ini SomeTests          # Runs Class
python Test.py --c keith.ini SomeTests.test_one # Runs test

HTH, Enjoy

like image 110
Keith Avatar answered Sep 04 '25 06:09

Keith