Generate pytest tests for Typer CLI commands. Includes fixtures (temp_storage, sample_data), CliRunner patterns, confirmation handling (y/n/--force), and edge case coverage. Use when user asks to "write tests for", "test my CLI", "add test coverage", or any CLI + test request.
Patterns for generating tests for Typer CLI commands.
conftest.pyimport json
import pytest
from typer.testing import CliRunner
@pytest.fixture
def runner():
"""CLI test runner."""
return CliRunner()
@pytest.fixture
def temp_storage(tmp_path, monkeypatch):
"""Empty storage for testing."""
storage_dir = tmp_path / ".task"
storage_dir.mkdir()
storage_file = storage_dir / "tasks.json"
storage_file.write_text(json.dumps({"version": 1, "tasks": []}))
monkeypatch.setenv("TASK_STORAGE_PATH", str(storage_file))
return storage_file
@pytest.fixture
def sample_data(temp_storage):
"""Pre-populated storage."""
data = {
"version": 1,
"tasks": [
{"title": "First task", "done": False, "priority": "low", "created_at": "2025-01-01T10:00:00", "due_date": None},
{"title": "Second task", "done": True, "priority": "high", "created_at": "2025-01-01T11:00:00", "due_date": None},
]
}
temp_storage.write_text(json.dumps(data))
return data
def test_<command>_<scenario>(runner, temp_storage):
# Arrange - via fixtures
# Act
result = runner.invoke(app, ["<command>", "<args>"])
# Assert
assert result.exit_code == 0
assert "<expected>" in result.output
from typer.testing import CliRunner
from task.main import app
runner = CliRunner()
# Basic
result = runner.invoke(app, ["add", "New task"])
# With options
result = runner.invoke(app, ["add", "Task", "--priority", "high"])
# With confirmation
result = runner.invoke(app, ["clear", "1"], input="y\n") # Accept
result = runner.invoke(app, ["clear", "1"], input="n\n") # Decline
# Skip confirmation
result = runner.invoke(app, ["clear", "1", "--force"])
class TestAdd:
def test_adds_task(self, runner, temp_storage):
result = runner.invoke(app, ["add", "New task"])
assert result.exit_code == 0
assert "Added" in result.output
def test_with_priority(self, runner, temp_storage):
result = runner.invoke(app, ["add", "Task", "--priority", "high"])
assert result.exit_code == 0
def test_empty_title_shows_error(self, runner, temp_storage):
result = runner.invoke(app, ["add", ""])
assert result.exit_code == 2
class TestList:
def test_shows_tasks(self, runner, sample_data):
result = runner.invoke(app, ["list"])
assert result.exit_code == 0
assert "First task" in result.output
def test_empty_state(self, runner, temp_storage):
result = runner.invoke(app, ["list"])
assert "No tasks" in result.output or "empty" in result.output.lower()
def test_with_filter(self, runner, sample_data):
result = runner.invoke(app, ["list", "--done"])
assert result.exit_code == 0
class TestDone:
def test_marks_done(self, runner, sample_data):
result = runner.invoke(app, ["done", "1"])
assert result.exit_code == 0
def test_not_found(self, runner, temp_storage):
result = runner.invoke(app, ["done", "999"])
assert result.exit_code == 1
assert "not found" in result.output.lower()
class TestClear:
def test_confirmed(self, runner, sample_data):
result = runner.invoke(app, ["clear", "1"], input="y\n")
assert result.exit_code == 0
assert "Deleted" in result.output
def test_declined(self, runner, sample_data):
result = runner.invoke(app, ["clear", "1"], input="n\n")
assert "Cancelled" in result.output
def test_force(self, runner, sample_data):
result = runner.invoke(app, ["clear", "1", "--force"])
assert result.exit_code == 0
def test_not_found(self, runner, temp_storage):
result = runner.invoke(app, ["clear", "999", "--force"])
assert result.exit_code == 1
| Category | Test Cases | |----------|------------| | Invalid Input | Empty string, wrong type, out of range | | Not Found | ID doesn't exist | | Boundary | Zero, negative, first/last item | | State | Already done, empty storage | | Confirmation | Accept (y), decline (n), force flag |
tests/test_<command>.pyconftest.pyCliRunner from typer.testing--forceuv run pytest # All tests
uv run pytest -v # Verbose
uv run pytest tests/test_add.py # Specific file
npx skills add https-deeplearning-ai/generating-cli-tests下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer