[PYTHON] Test the version of the argparse module

Issues you want to address

Suppose there is such a parser.

main.py


__version__ = '0.0.1'

def prepare_parser():
    parser = ArgumentParser(description=(__doc__),
                            formatter_class=RawDescriptionHelpFormatter)
    parser.add_argument('-d', '--debug', action='store_true',
                        help='Show debug log')
    parser.add_argument('-v', '--version', action='version',
                        version=__version__,
                        help='Show version and exit')
    return parser

Suppose you want to test that this verison part can be used properly.

The trouble is that parser.parse_args (['-v']) will cause SystemExit to fly at that point.

>>> from main import prepare_parser
>>> parser = prepare_parser()
>>> args = parser.parse_args(['-v'])
0.0.1
$     <--The interpreter has ended because the System Exit flies.

This is a specification of the argparse version action.

'version' - This expects a version= keyword argument in the add_argument() call, and prints version information and exits when invoked:

https://docs.python.org/3.6/library/argparse.html#action

I don't want sys.exit () to fly casually in the middle of a unit test. Also, I want to confirm that the version is output properly.

There could be a patch (https://docs.python.jp/3/library/unittest.mock-examples.html#patch-decorators), but if possible I would like to treat the contents of the argparse as a black box.

What i did

Try the following.

tests.py


from contextlib import contextmanager
from io import StringIO
import unittest
import sys

from main import prepare_parser, __version__

@contextmanager
def capture_stdout(command, *args, **kwargs):
    out, sys.stdout = sys.stdout, StringIO()
    try:
        command(*args, **kwargs)
    finally:
        sys.stdout.seek(0)
        yield sys.stdout.read()
        sys.stdout = out


class MyTest(unittest.TestCase):
    def test_version(self):
        parser = prepare_parser()
        with self.assertRaises(SystemExit):
            with capture_stdout(parser.parse_args, ['-v']) as output:
                self.assertIsNotNone(output)
                self.assertEqual(__version__, output.rstrip())

        with self.assertRaises(SystemExit):
            with capture_stdout(parser.parse_args,
                                ['--version']) as output:
                self.assertIsNotNone(output)
                self.assertEqual(__version__, output.rstrip())


if __name__ == '__main__':
    unittest.main()

By having the context manager yield the string that was sent to stdout when the exception was blown, hoping that SystemExit would be skipped.

I came to be able to test.

When commenting out the optional part that parses -v etc.

$ python tests.py
usage: tests.py [-h] [-d]
tests.py: error: unrecognized arguments: -v
F
======================================================================
FAIL: test_version (__main__.MyTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests.py", line 26, in test_version
    self.assertEqual(__version__, output.rstrip())
AssertionError: '0.0.1' != ''
- 0.0.1
+


----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

If you comment in

$ python tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Impressions

I don't think it's the kind of test I want to do. Is this test vulnerable ...? I'm not sure.

Is there a better way?

Environment used for confirmation

reference

Recommended Posts

Test the version of the argparse module
Let's use the Python version of the Confluence API module.
Raise the version of pyenv itself
Test the goodness of fit of the distribution
pyenv-change the python version of virtualenv
Change the Python version of Homebrew
What is the default TLS version of the python requests module?
How to check the version of Django
Pass the path of the imported python module
About the virtual environment of python version 3.7
[Python] Try pydash of the Python version of lodash
Check the path of the Python imported module
Migemo version of the: find command,: mfind
About the test
Try the python version of emacs-org parser orgparse
The story of making the Mel Icon Generator version2
[Python] Test the moon matagi of relative delta
Use the latest version of PyCharm on Ubuntu
A note about the python version of python virtualenv
Try the free version of Progate [Python I]
[Python] A rough understanding of the logging module
Try using the collections module (ChainMap) of python3
The beginning of cif2cell
Scraping the usage history of the community cycle PhantomJS version
Install the latest version of CMake on Ubuntu 18.04.4 LTS
Get the GNOME version
The meaning of self
Open Chrome version of LINE from the command line [Linux]
Installation of OpenMDAO (version 1.7.1)
Find out the version of the language you are running
[python] Get the list of classes defined in the module
the zen of Python
The story of sys.path.append ()
Let's test the medical collapse hypothesis of the new coronavirus
Manage the package version number of requirements.txt with pip-tools
How to access the global variable of the imported module
The latest version of Pillow 7.0.0 will kill the pytorch transform.
Check the type and version of your Linux distribution
Summary of test method
Dynamically load the module.
Revenge of the Types: Revenge of types
I tried running the sample code of the Ansible module
Notes on the version of CUDA, cuDNN where tensorflow-gpu worked
Put the latest version of Python on linux (Debian) on Chromebook
How to test the attributes added by add_request_method of pyramid
Make the display of Python module exceptions easier to understand
View using the python module of Nifty Cloud mobile backend
(Note) How to pass the path of your own module
Hook to the first import of the module and print the module path
[Linux] [kernel module] Specify / limit the execution CPU of kthread
Install the latest version of Git on your Linux server
Commands and files to check the version of CentOS Linux
2015-11-26 python> Display the function list of the module> import math> dir (math)
The story of downgrading the version of tensorflow in the demo of Mask R-CNN.
Scraping the result of "Schedule-kun"
Automatically fetch the installed version
10. Counting the number of lines
The story of building Zabbix 4.4
Towards the retirement of Python2
[Apache] The story of prefork
For the G test 2020 # 2 exam