I usually build command-line tools using Click (and my click-app cookiecutter template), which includes a really nice set of tools for writing tests.
Today I decided to try building a tool called stream-delay using argparse from the Python standard library, since it didn't need any other dependencies.
The one challenge I had was how to write the tests. I used pytest as a test-only dependency.
Here's the pattern I came up with, using the capsys pytest fixture to capture standard output from my tool.
from stream_delay import main import pytest @pytest.mark.parametrize("option", ("-h", "--help")) def test_help(capsys, option): try: main([option]) except SystemExit: pass output = capsys.readouterr().out assert "Stream one or more files with a delay" in output
main() function starts like this:
import argparse, sys parser = argparse.ArgumentParser( description="Stream one or more files with a delay between each line" ) parser.add_argument("files", type=argparse.FileType("r"), nargs="*", default=["-"]) parser.add_argument("-d", "--delay-in-ms", type=int, default=100) def main(args=None): parsed_args = parser.parse_args(args) delay_in_s = float(parsed_args.delay_in_ms) / 1000 # ...
As you can see,
main() takes an optional list of arguments. The default for that is
None which will cause
argparse to read
sys.argv - but I can inject arguments to the function from my tests if I need to.
I'm catching the
SystemExit exception because this will be raised by default if you use
--help - but I still want to finish my test execution so I can inspect the captured output.
Created 2022-01-08T12:42:34-08:00 · Edit