Home > Software engineering >  Test of a CLI program with mutually exclusive arguments throws SystemExit instead of expected ValueE
Test of a CLI program with mutually exclusive arguments throws SystemExit instead of expected ValueE

Time:10-11

I have a command line application that can accept either the command line argument --input_files or --unigrams, but not both at the same time:

import click
import pathlib
from typing import Optional

@click.command()
@click.option(
    "--input_files",
    default=None,
    type=str,
    help="Comma-separated list of one-sentence-per-line raw corpus files",
)
@click.option("--unigrams", default=None, type=str, help="Comma-separated list of unigrams")
@click.option(
    "--model_path",
    default="spm/models",
    type=click.Path(file_okay=False, path_type=pathlib.Path),
    help="Output model path",
)
def minimal(
    model_path: pathlib.Path,
    input_files: Optional[str],
    unigrams: Optional[str]
) -> str:
    if input_files and unigrams:
        raise ValueError("Only one of input_files or unigrams can be specified.")

    if input_files:
        click.echo(f"input_files: {input_files}")

    if unigrams:
        click.echo(f"Unigrams: {unigrams}")

I wrote a test for the case where both arguments are passed, using file system isolation, and expect the ValueError to be raised:

from click.testing import CliRunner

def test_minimal(tmp_path: str) -> None:
    runner = CliRunner()
    with runner.isolated_filesystem(temp_dir=tmp_path):
        result = runner.invoke(
            minimal,
            ["--model_path", tmp_path, "--input-files", "test.txt", "--unigrams", "a,b"],
        )
        assert isinstance(result.exception, ValueError)
        assert "Only one of input_files or unigrams can be specified." in str(result.exception)


but this test fails because a SystemExit is raised:

=================================================================================== FAILURES ====================================================================================
_________________________________________________________________________________ test_minimal __________________________________________________________________________________

tmp_path = PosixPath('/tmp/pytest-of-biogeek/pytest-2/test_minimal0')

    def test_minimal(tmp_path: str) -> None:
        runner = CliRunner()
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(
                train_spm.minimal,
                ["--model_path", tmp_path, "--input-files", "test.txt", "--unigrams", "a,b"],
            )
>           assert isinstance(result.exception, ValueError)
E           assert False
E               where False = isinstance(SystemExit(2), ValueError)
E                 where SystemExit(2) = <Result SystemExit(2)>.exception

stackoverflow_test.py:20: AssertionError
============================================================================ short test summary info ============================================================================
FAILED projects/stackoverflow_test.py::test_minimal - assert False

What am I doing wrong?

CodePudding user response:

SystemExit(2) is a UsageError as referenced by this answer. This means that something is likely incorrect in the command line script.

When inspecting the original file, you define the argument flag as --input_files. However, the test script is invoking --input-files.

Replacing the dash with an underscore fixes your issue and the test passes.

  • Related