# Test Agent Skill
A specialized agent for writing and running tests with dry-run mode for the Siigo MCP server.
## Overview
This skill helps you write tests that:
- Use **real Siigo credentials** for authentication
- Execute **read operations** against the real API
- **Mock write operations** (create/update/delete) to prevent mutations
## Dry-Run Mode
When `DRY_RUN=true`:
- `GET` requests work normally (safe, read-only)
- `POST/PUT/DELETE` are intercepted and return mock responses
- Operations are logged for verification
## Available Fixtures
Use these in `tests/conftest.py`:
```python
# Real client for read-only tests
@pytest.fixture
async def siigo_client(real_credentials):
client = SiigoClient(**real_credentials)
yield client
await client.close()
# Dry-run client for mutation tests
@pytest.fixture
async def dry_run_client(real_credentials, dry_run_env):
client = DryRunSiigoClient(**real_credentials)
yield client
await client.close()
```
## Writing Tests
### Read-Only Tests (Safe)
```python
@pytest.mark.asyncio
async def test_list_customers(siigo_client):
"""Safe to run - only reads data."""
result = await siigo_client.get("/customers")
assert isinstance(result, dict)
assert "results" in result
```
### Mutation Tests (Use Dry-Run)
```python
@pytest.mark.asyncio
async def test_create_customer(dry_run_client):
"""Safe - uses dry-run client, no actual creation."""
result = await dry_run_client.post("/customers", {
"type": "Person",
"id_type": {"code": "13"},
"identification": "123456789",
"name": ["John", "Doe"],
})
assert result["dry_run"] is True
assert result["action"] == "create"
```
## Running Tests
```bash
# Run all tests with dry-run (safe)
DRY_RUN=true pytest tests/
# Run only read-only tests (always safe)
pytest tests/test_reference.py
# Run specific test
DRY_RUN=true pytest tests/test_customers.py::test_create_customer -v
```
## Operations Classification
### Safe to Run (Read-Only)
- `get_taxes`, `get_payment_types`, `get_document_types`
- `get_warehouses`, `get_users`, `get_account_groups`
- `list_customers`, `get_customer`
- `list_products`, `get_product`
- `list_invoices`, `get_invoice`, `get_invoice_pdf`
- `list_credit_notes`, `get_credit_note`
- `list_journals`, `get_journal`
### Require Dry-Run (Mutations)
- `create_customer`, `update_customer`, `delete_customer`
- `create_product`, `update_product`, `delete_product`
- `create_invoice`, `update_invoice`, `delete_invoice`
- `stamp_invoice`, `send_invoice_email`, `annul_invoice`
- `create_credit_note`, `create_journal`
## Test Data Examples
### Customer
```python
customer_data = {
"type": "Person", # or "Company"
"id_type": {"code": "13"}, # 13=Cédula, 31=NIT
"identification": "1234567890",
"name": ["Juan", "Pérez"],
"vat_responsible": False,
}
```
### Product
```python
product_data = {
"code": "TEST-001",
"name": "Test Product",
"account_group": 1234,
"type": "Product", # or "Service"
"stock_control": False,
}
```
### Invoice
```python
invoice_data = {
"document": {"id": 12345},
"customer": {"id": "customer-guid"},
"items": [{
"code": "PROD-001",
"quantity": 1,
"price": 10000,
"taxes": [{"id": 1}],
}],
"payments": [{
"id": 1,
"value": 10000,
"due_date": "2024-12-31",
}],
}
```
## Workflow
1. **Write test** using appropriate fixture (`siigo_client` or `dry_run_client`)
2. **Run with dry-run** to verify logic without mutations
3. **Check logs** to see what would have been executed
4. **Iterate** until test passes