Files
template-skill-cli/scripts/test_@@PKG@@.py

61 lines
1.7 KiB
Python

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["click", "requests", "pytest"]
# ///
"""Smoke tests for @@PKG@@.py — run them with `./scripts/test_@@PKG@@.py`.
click's CliRunner invokes the CLI in-process, so a skill gets real tests for the
price of a file. Add a case whenever you add a command; at minimum keep the
"--help works" and "--json is parseable" ones, they catch most scaffolding slips.
"""
import importlib.util
import json
import sys
from pathlib import Path
import pytest
from click.testing import CliRunner
_spec = importlib.util.spec_from_file_location("@@PKG@@", Path(__file__).with_name("@@PKG@@.py"))
_mod = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_mod)
cli = _mod.cli
@pytest.fixture
def runner():
return CliRunner()
def test_help(runner):
res = runner.invoke(cli, ["--help"])
assert res.exit_code == 0
assert "run" in res.output and "send" in res.output
def test_run_json_is_parseable(runner):
res = runner.invoke(cli, ["--json", "run", "example"])
assert res.exit_code == 0
assert json.loads(res.output)["target"] == "example"
def test_steps_keep_command_line_order(runner):
res = runner.invoke(
cli,
["--json", "run", "example", "--step", "wait:#a", "--step", "click:#b", "--step", "wait:#c"],
)
assert res.exit_code == 0
assert [s["kind"] for s in json.loads(res.output)["steps"]] == ["wait", "click", "wait"]
def test_bad_step_kind_is_a_usage_error(runner):
res = runner.invoke(cli, ["run", "example", "--step", "frobnicate:#a"])
assert res.exit_code == 2
assert "is not a step" in res.output
if __name__ == "__main__":
sys.exit(pytest.main([__file__, "-q"]))