agentsclimarketplace

Generating cli tests

Skill ComeOnOliver/skillshub/skills/https-deeplearning-ai/sc-agent-skills-files/generating-cli-tests

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill generating-cli-tests

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

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.

SKILL.md

5.3 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it

Generating CLI Tests

Patterns for generating tests for Typer CLI commands.

Workflow

  1. Identify command type (Create/Read/Update/Delete/Bulk)
  2. Ensure fixtures exist in conftest.py
  3. Write tests using scenarios below
  4. Run tests to verify

Fixtures (conftest.py)

import 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

Test Structure (AAA)

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

CliRunner Usage

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"])

Test Scenarios by Command Type

Create/Add

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

Read/List

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

Update/Done

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()

Delete/Clear

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

Edge Cases to Cover

CategoryTest Cases
Invalid InputEmpty string, wrong type, out of range
Not FoundID doesn't exist
BoundaryZero, negative, first/last item
StateAlready done, empty storage
ConfirmationAccept (y), decline (n), force flag

Checklist

  • Test file: tests/test_<command>.py
  • Fixtures in conftest.py
  • Uses CliRunner from typer.testing
  • AAA structure (Arrange, Act, Assert)
  • Tests exit codes: 0, 1, 2
  • Destructive commands: tests y/n and --force
  • Output assertions check expected messages

Running Tests

uv run pytest                       # All tests
uv run pytest -v                    # Verbose
uv run pytest tests/test_add.py    # Specific file

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,167. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.