Skip to Content

Testing

TL;DR

Use TestClient to test skill commands without running the full CLI. It supports both keyword-based (client.run) and CLI-style (client.run_cli) invocation. Combine with pytest-asyncio for async tests.

Setup

Add dev dependencies to pyproject.toml:

[project.optional-dependencies] dev = [ "pytest>=8.0", "pytest-asyncio>=0.24", "pytest-cov>=6.0", "ruff>=0.8", ] [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"]

Install:

pip install -e '.[dev]'

TestClient

from cmdop_skill import TestClient from my_skill._skill import skill client = TestClient(skill)

Keyword invocation

Pass arguments as Python keyword arguments:

async def test_check_domain(): client = TestClient(skill) result = await client.run("check", domain="github.com", timeout=5) assert result["ok"] is True assert result["domain"] == "github.com" assert result["days_left"] > 0

CLI-style invocation

Pass arguments as strings, exactly like the command line:

async def test_check_cli(): client = TestClient(skill) result = await client.run_cli("check", "--domain", "github.com", "--timeout", "5") assert result["ok"] is True

Context manager

Use async with to ensure teardown hooks run:

async def test_with_lifecycle(): async with TestClient(skill) as client: result = await client.run("check", domain="github.com") assert result["ok"] is True # teardown has run at this point

Test patterns

Error cases

async def test_invalid_domain(): client = TestClient(skill) result = await client.run("check", domain="not-a-domain") assert result["ok"] is False assert "error" in result

Mocking external calls

from unittest.mock import AsyncMock, patch async def test_with_mock(): client = TestClient(skill) with patch("my_skill._skill.fetch_cert", new_callable=AsyncMock) as mock: mock.return_value = {"days_left": 42, "issuer": "Let's Encrypt"} result = await client.run("check", domain="example.com") assert result["days_left"] == 42 mock.assert_called_once_with("example.com", timeout=10)

Shared fixtures

In tests/conftest.py:

import pytest from cmdop_skill import TestClient from my_skill._skill import skill @pytest.fixture def client(): return TestClient(skill)

Then in tests:

async def test_check(client): result = await client.run("check", domain="github.com") assert result["ok"] is True

Running tests

make test # via Makefile pytest tests/ -v # directly pytest tests/ -v --cov=src # with coverage
Last updated on