I have a command-line script with Python-click with an argument and option:
# console.py
import click
@click.command()
@click.version_option()
@click.argument("filepath", type=click.Path(exists=True), default=".")
@click.option(
"-m",
"--max-size",
type=int,
help="Max size in megabytes.",
default=20,
show_default=True,
)
def main(filepath: str, max_size: int) -> None:
max_size_bytes = max_size * 1024 * 1024 # convert to MB
if filepath.endswith(".pdf"):
print("success")
else:
print(max_size_bytes)
Both the argument and option have default values and work on the command-line and using the CLI it behaves as expected. But when I try testing it following Click documentation and debug it, it does not enter the first line:
# test_console.py
from unittest.mock import Mock
import click.testing
import pytest
from pytest_mock import MockFixture
from pdf_split_tool import console
@pytest.fixture
def runner() -> click.testing.CliRunner:
"""Fixture for invoking command-line interfaces."""
return click.testing.CliRunner()
@pytest.fixture
def mock_pdf_splitter_pdfsplitter(mocker: MockFixture) -> Mock:
"""Fixture for mocking pdf_splitter.PdfSplitter."""
return mocker.patch("pdf_split_tool.pdf_splitter.PdfSplitter", autospec=True)
def test_main_uses_specified_filepath(
runner: click.testing.CliRunner,
mock_pdf_splitter_pdfsplitter: Mock,
) -> None:
"""It uses the specified filepath."""
result = runner.invoke(console.main, ["test.pdf"])
assert result.exit_code == 0
I couldn't see why it is giving since the debugger did not enter the first line of function main(). Any ideas of what could be wrong?
The failure is due to following error.
(pdb)print result.output
"Usage: main [OPTIONS] [FILEPATH]\nTry 'main --help' for help.\n\nError: Invalid value for '[FILEPATH]': Path 'test.pdf' does not exist.\n"
This is happening due to following code in console.py which checks if the filepath exists.
@click.argument("filepath", type=click.Path(exists=True), default=".")
One way to test creating a temporary file is using afterburner's code:
# test_console.py
def test_main_uses_specified_filepath() -> None:
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
with open('test.pdf', 'w') as f:
f.write('Hello World!')
result = runner.invoke(main, ["test.pdf"])
assert result.exit_code == 0