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
My 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 -h
or --help
- but I still want to finish my test execution so I can inspect the captured output.
Complete code:
Created 2022-01-08T12:42:34-08:00 · Edit