-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests: Add test to guarantee CLI is reachable
There are tests for the CLI but these use click's `CliRunner` which calls the commands directly from the Python API instead of calling the actual CLI script. This would not catch if the script is not properly installed or reachable. Here a test is added that tries to call the CLI through a subprocess, which simulates the real situation of a user invoking it. This test would have caught the missing imports that were accidentally removed by the `ruff` linter.
- Loading branch information
Showing
2 changed files
with
48 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
"""Module for the command line interface.""" | ||
from .launch import cmd_launch # noqa: F401 | ||
from .plot import cmd_plot # noqa: F401 | ||
from .root import cmd_root # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
"""Tests for CLI commands.""" | ||
from __future__ import annotations | ||
|
||
import subprocess | ||
|
||
import click | ||
import pytest | ||
from aiida_common_workflows.cli import cmd_root | ||
|
||
|
||
def recurse_commands(command: click.Command, parents: list[str] | None = None): | ||
"""Recursively return all subcommands that are part of ``command``. | ||
:param command: The click command to start with. | ||
:param parents: A list of strings that represent the parent commands leading up to the current command. | ||
:returns: A list of strings denoting the full path to the current command. | ||
""" | ||
if isinstance(command, click.Group): | ||
for command_name in command.commands: | ||
subcommand = command.get_command(None, command_name) | ||
if parents is not None: | ||
subparents = [*parents, command.name] | ||
else: | ||
subparents = [command.name] | ||
yield from recurse_commands(subcommand, subparents) | ||
|
||
if parents is not None: | ||
yield [*parents, command.name] | ||
else: | ||
yield [command.name] | ||
|
||
|
||
@pytest.mark.parametrize('command', recurse_commands(cmd_root)) | ||
@pytest.mark.parametrize('help_option', ('--help', '-h')) | ||
def test_commands_help_option(command, help_option): | ||
"""Test the help options for all subcommands of the CLI. | ||
The usage of ``subprocess.run`` is on purpose because using :meth:`click.Context.invoke`, which is used by the | ||
``run_cli_command`` fixture that should usually be used in testing CLI commands, does not behave exactly the same | ||
compared to a direct invocation on the command line. The invocation through ``invoke`` does not go through all the | ||
parent commands and so might not get all the necessary initializations. | ||
""" | ||
result = subprocess.run([*command, help_option], check=False, capture_output=True, text=True) | ||
assert result.returncode == 0, result.stderr | ||
assert 'Usage:' in result.stdout |