Is there a way to give the argparse command (Python 2.7) to remove the arguments found from sys.argv?

I am fully accustomed to the development process for what turns into a pretty substantial Python 2.7 project. Right now I have all the unittest classes combined into their own module, tests.py , which costs about 3,300 lines. This is crazy, big, impossible to navigate around bad practice, etc.

So my current task is to reorganize it into submodules. As part of this refactoring, I want to simplify just running a subset of tests from the command line. For example:

 $ python tests.py --all <--- runs *all* tests $ python tests.py --utils_base <--- runs all tests on .utils $ python tests.py --utils_vector <--- runs all tests on .utils.vector $ python tests.py --utils_base --utils_vector <--- runs all tests on .utils.vector & .utils 

So, I started getting settings with argparse . I got the basic setup of ArgumentParser without any problems, and the help message showed simply:

 $ python tests.py -h usage: tests.py [-h] [--all] [--utils_base] optional arguments: -h, --help show this help message and exit Global Options: --all Run all tests (overrides any other selections) opan.base.utils Tests: --utils_base Run all .utils tests 

However, when I went to run some tests, it crashed with the error "argument not recognized":

 $ python tests.py --all option --all not recognized Usage: tests.py [options] [test] [...] Options: -h, --help Show this message -v, --verbose Verbose output -q, --quiet Minimal output -f, --failfast Stop on first failure -c, --catch Catch control-C and display results -b, --buffer Buffer stdout and stderr during test runs Examples: tests.py - run default set of tests tests.py MyTestSuite - run suite 'MyTestSuite' tests.py MyTestCase.testSomething - run MyTestCase.testSomething tests.py MyTestCase - run all 'test*' test methods in MyTestCase 

After some debugging, I finally realized that the command line arguments that need to be analyzed in tests.py are stored in sys.argv and passed to unittest.main . (Looking back, carefully read the Examples: error message section, which should have told me much earlier.)

So, to solve the problem, I added the marked code as follows to clear my user arguments from sys.argv before passing control to unittest.main :

 # Arguments for selecting test suites ALL = 'all' UTILS_BASE = 'utils_base' # Collecting the args together for iteration later test_args = [ALL, UTILS_BASE] ... # Strip from sys.argv any test arguments that are present for a in test_args: <--- str_arg = '--{0}'.format(a) <--- ADDING THESE MAKES UNITTEST HAPPY if str_arg in sys.argv: <--- sys.argv.remove(str_arg) <--- 

Is it possible to tell argparse in .remove arguments it found from sys.argv , possibly in the construction of ArgumentParser ? I looked at the argparse doc page, but for me life cannot find an option that will do this.

0
python argparse
source share
1 answer

Do you want parse_known_args ()

 from __future__ import print_function import argparse import sys def main(): print(sys.argv) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('--all', action='store_true') parser.add_argument('--utils_base', action='store_true') args, left = parser.parse_known_args() sys.argv = sys.argv[:1]+left main() 

Although, I have to ask. Why are you writing your own test runner? The unittest module allows you to run specific test commands from cli:

 # run test from a spefiic class $ python -m unittest module.tests.group.TestSpecific # all possible options $ python -m unittest --help Usage: python -m unittest [options] [tests] Options: -h, --help Show this message -v, --verbose Verbose output -q, --quiet Minimal output -f, --failfast Stop on first failure -c, --catch Catch control-C and display results -b, --buffer Buffer stdout and stderr during test runs Examples: python -m unittest test_module - run tests from test_module python -m unittest module.TestClass - run tests from module.TestClass python -m unittest module.Class.test_method - run specified test method [tests] can be a list of any number of test modules, classes and test methods. Alternative Usage: python -m unittest discover [options] Options: -v, --verbose Verbose output -f, --failfast Stop on first failure -c, --catch Catch control-C and display results -b, --buffer Buffer stdout and stderr during test runs -s directory Directory to start discovery ('.' default) -p pattern Pattern to match test files ('test*.py' default) -t directory Top level directory of project (default to start directory) For test discovery all test modules must be importable from the top level directory of the project. 

If you need even more flexibility when grouping and running tests, I would suggest looking at nosetest

+2
source share

All Articles