Dead Simple: PyTest and ArgParse

Adam Hughes
Programmer’s Journey
2 min readAug 4, 2023

You’re writing a Python script with an argparser and want to test it without mocks and hacks. You’ve been googling for 20 minutes. You’ve landed here. Go no further.

Here is a template for a parser that takes a single argument myfile

import argparse as ap
import sys

def _parse(args=None) -> ap.Namespace:
parser = ap.ArgumentParser()
parsed = parser.parse_args(args)

def start(myfile) -> None:
print(f'my file: {myfile}')

if __name__ == "__main__":

I like this format because it can be called from command line

python "foofile"

Or used as an import

from coolapp import start


Happy paths are fairly straightforward. Using start() directly or implicitly via sys.argv
from coolapp import start, _parse
import sys

def test_coolapp():
""" Direct import of start """

def test_coolapp_sysargs():
""" Called through __main__ (eg. python myfile.txt) """

To be honest — I’d rather not have to import _parse and instead just test the logic under __name__ == "__main__" , but that requires too much work.

Invalid input is also important to test. Calling argparser with no args should produce a message like:


usage: [-h] myfile error: the following arguments are required: myfile

How do we test this? It’s non-trivial becaus argparser doesn’t raise a normal exception, it throws a SystemExit .

In typical python docs fashion, there’s a way in the py docs that is lacking a real-world example. It comes down to the capsys pytest fixture.

def test_coolapp_no_args(capsys):
""" ie. python """
with pytest.raises(SystemExit):
captured = capsys.readouterr()
assert "the following arguments are required: myfile" in captured.err

def test_coolapp_extra_args(capsys):
""" ie. python arg1 arg2 """
with pytest.raises(SystemExit):
_parse(['arg1', 'arg2'])
captured = capsys.readouterr()
assert "unrecognized arguments: arg2" in captured.err


You may have noticed_parse(args=None)This is necessary for coolapp to be a script that gets installed from . As per this packaging guide and this SO discussion, our setup file can now reference the _parse method 

'console_scripts': ['coolapp=package.coolapp:_parse

And then voila , upon pip install coolapp , we can then access it from anywhere.

FileNotFoundError: [Errno 2] No such file or directory: ''



Adam Hughes
Programmer’s Journey

Software Developer, Scientist, Muay Thai, hackDontSlack