api-testing

Test FastAPI endpoints with pytest and generate API documentation. Use when creating new APIs or verifying existing endpoints work correctly.

16 stars

Best use case

api-testing is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Test FastAPI endpoints with pytest and generate API documentation. Use when creating new APIs or verifying existing endpoints work correctly.

Teams using api-testing should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/api-testing/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/backend/api-testing/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/api-testing/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How api-testing Compares

Feature / Agentapi-testingStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Test FastAPI endpoints with pytest and generate API documentation. Use when creating new APIs or verifying existing endpoints work correctly.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

You help test FastAPI endpoints for the QA Team Portal backend using pytest and manual testing tools.

## When to Use This Skill

- Testing new API endpoints after creation
- Verifying authentication/authorization works
- Testing CRUD operations
- Checking error handling and validation
- Load/stress testing APIs
- Generating API documentation examples

## Testing Approaches

### 1. Automated Testing with Pytest

#### Unit Tests (Fast, Isolated)

```python
# tests/unit/test_team_service.py
import pytest
from app.services.team_service import TeamService

def test_validate_team_member_data():
    service = TeamService()
    data = {"name": "John Doe", "role": "QA Lead"}
    assert service.validate(data) is True

def test_validate_rejects_invalid_email():
    service = TeamService()
    data = {"name": "John", "email": "invalid"}
    with pytest.raises(ValueError):
        service.validate(data)
```

#### Integration Tests (Full API Flow)

```python
# tests/integration/test_api_team_members.py
import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_get_team_members():
    response = client.get("/api/v1/team-members")
    assert response.status_code == 200
    assert isinstance(response.json(), list)

def test_create_team_member_requires_auth():
    data = {"name": "John Doe", "role": "QA Lead"}
    response = client.post("/api/v1/team-members", json=data)
    assert response.status_code == 401

def test_create_team_member_with_auth(admin_token):
    headers = {"Authorization": f"Bearer {admin_token}"}
    data = {
        "name": "John Doe",
        "role": "QA Lead",
        "email": "john@example.com"
    }
    response = client.post("/api/v1/team-members", json=data, headers=headers)
    assert response.status_code == 201
    assert response.json()["name"] == "John Doe"

def test_update_team_member(admin_token, test_team_member):
    headers = {"Authorization": f"Bearer {admin_token}"}
    data = {"name": "Jane Doe"}
    response = client.put(
        f"/api/v1/team-members/{test_team_member.id}",
        json=data,
        headers=headers
    )
    assert response.status_code == 200
    assert response.json()["name"] == "Jane Doe"

def test_delete_team_member(admin_token, test_team_member):
    headers = {"Authorization": f"Bearer {admin_token}"}
    response = client.delete(
        f"/api/v1/team-members/{test_team_member.id}",
        headers=headers
    )
    assert response.status_code == 204
```

#### Pytest Fixtures

```python
# tests/conftest.py
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.main import app
from app.db.base import Base
from app.api.deps import get_db

# Test database
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
TestingSessionLocal = sessionmaker(bind=engine)

@pytest.fixture(scope="function")
def db():
    Base.metadata.create_all(bind=engine)
    db = TestingSessionLocal()
    try:
        yield db
    finally:
        db.close()
        Base.metadata.drop_all(bind=engine)

@pytest.fixture
def client(db):
    def override_get_db():
        try:
            yield db
        finally:
            db.close()
    app.dependency_overrides[get_db] = override_get_db
    return TestClient(app)

@pytest.fixture
def admin_token(client):
    response = client.post("/api/v1/auth/login", json={
        "email": "admin@test.com",
        "password": "testpass123"
    })
    return response.json()["access_token"]

@pytest.fixture
def test_team_member(db):
    from app.models.team_member import TeamMember
    member = TeamMember(
        name="Test User",
        role="QA Engineer",
        email="test@test.com"
    )
    db.add(member)
    db.commit()
    db.refresh(member)
    return member
```

### 2. Manual Testing with curl

```bash
# Health check
curl http://localhost:8000/health

# Get all team members (public)
curl http://localhost:8000/api/v1/team-members

# Login
TOKEN=$(curl -X POST http://localhost:8000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@test.com","password":"pass"}' \
  | jq -r '.access_token')

# Create team member (admin)
curl -X POST http://localhost:8000/api/v1/team-members \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "role": "QA Lead",
    "email": "john@example.com"
  }'

# Upload profile photo
curl -X POST http://localhost:8000/api/v1/team-members/123/photo \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@profile.jpg"

# Get with filters
curl "http://localhost:8000/api/v1/team-members?role=QA%20Lead&active=true"
```

### 3. Testing with HTTPie (Prettier Output)

```bash
# Install httpie
pip install httpie

# Login
http POST localhost:8000/api/v1/auth/login email=admin@test.com password=pass

# Create with auth
http POST localhost:8000/api/v1/team-members \
  Authorization:"Bearer $TOKEN" \
  name="John Doe" \
  role="QA Lead" \
  email="john@example.com"

# Pretty print JSON
http GET localhost:8000/api/v1/team-members | jq '.'
```

## Running Tests

```bash
cd backend

# Run all tests
uv run pytest

# Run with verbose output
uv run pytest -v

# Run specific test file
uv run pytest tests/integration/test_api_team_members.py

# Run specific test
uv run pytest tests/integration/test_api_team_members.py::test_create_team_member

# Run with coverage
uv run pytest --cov=app --cov-report=html

# Run only integration tests
uv run pytest tests/integration/

# Show print statements
uv run pytest -s

# Stop on first failure
uv run pytest -x

# Run tests matching pattern
uv run pytest -k "team_member"
```

## Test Coverage

```bash
# Generate coverage report
uv run pytest --cov=app --cov-report=term-missing

# Generate HTML report
uv run pytest --cov=app --cov-report=html
open htmlcov/index.html

# Coverage for specific module
uv run pytest --cov=app.api.v1.endpoints --cov-report=term
```

## Load Testing

```bash
# Install locust
uv pip install locust

# Create locustfile.py
cat > locustfile.py <<'EOF'
from locust import HttpUser, task, between

class APIUser(HttpUser):
    wait_time = between(1, 3)

    @task
    def get_team_members(self):
        self.client.get("/api/v1/team-members")

    @task(3)
    def get_updates(self):
        self.client.get("/api/v1/updates")
EOF

# Run load test
uv run locust -f locustfile.py --host=http://localhost:8000

# Or headless mode
uv run locust -f locustfile.py --host=http://localhost:8000 \
  --users 100 --spawn-rate 10 --run-time 1m --headless
```

## API Documentation Testing

```bash
# Access interactive docs
open http://localhost:8000/api/v1/docs

# Get OpenAPI schema
curl http://localhost:8000/api/v1/openapi.json | jq '.' > openapi.json

# Validate OpenAPI schema
npx @stoplight/spectral-cli lint openapi.json
```

## Test Checklist

For each endpoint, verify:

- [ ] **Success cases** - Returns 200/201/204 as expected
- [ ] **Authentication** - Returns 401 without token
- [ ] **Authorization** - Returns 403 for insufficient permissions
- [ ] **Validation** - Returns 422 for invalid data
- [ ] **Not Found** - Returns 404 for non-existent resources
- [ ] **Edge cases** - Empty lists, null values, boundary conditions
- [ ] **Error handling** - Doesn't expose sensitive info in errors
- [ ] **Rate limiting** - Enforced on sensitive endpoints
- [ ] **CORS** - Allows configured origins only
- [ ] **Response format** - Matches schema definition

## Common Test Patterns

### Testing Authentication

```python
def test_endpoint_requires_authentication(client):
    response = client.post("/api/v1/admin/users")
    assert response.status_code == 401

def test_endpoint_rejects_expired_token(client, expired_token):
    headers = {"Authorization": f"Bearer {expired_token}"}
    response = client.get("/api/v1/admin/users", headers=headers)
    assert response.status_code == 401
```

### Testing Validation

```python
def test_rejects_invalid_email(client, admin_token):
    headers = {"Authorization": f"Bearer {admin_token}"}
    data = {"name": "John", "email": "invalid"}
    response = client.post("/api/v1/team-members", json=data, headers=headers)
    assert response.status_code == 422
    assert "email" in response.json()["detail"][0]["loc"]
```

### Testing Pagination

```python
def test_pagination_limits_results(client):
    response = client.get("/api/v1/team-members?limit=5")
    assert len(response.json()) <= 5

def test_pagination_skip_offset(client):
    response1 = client.get("/api/v1/team-members?skip=0&limit=2")
    response2 = client.get("/api/v1/team-members?skip=2&limit=2")
    assert response1.json()[0]["id"] != response2.json()[0]["id"]
```

## Output Format

After testing, report:

1. **Tests Run**: X passed, Y failed
2. **Coverage**: X% of code covered
3. **Failed Tests**: List with error messages
4. **Performance**: Average response time for key endpoints
5. **Issues Found**: Any bugs or unexpected behavior
6. **Recommendations**: Suggested improvements

## Best Practices

1. **Test pyramid**: More unit tests, fewer integration tests
2. **Independent tests**: Each test should be isolated
3. **Descriptive names**: `test_create_team_member_requires_admin_role`
4. **Use fixtures**: Share test data setup
5. **Test error cases**: Not just happy path
6. **Mock external services**: Don't depend on external APIs
7. **Fast tests**: Keep test suite under 1 minute if possible

Related Skills

ai-powered-pentesting

16
from diegosouzapw/awesome-omni-skill

Guide for AI-powered penetration testing tools, red teaming frameworks, and autonomous security agents.

ab-testing-analyzer

16
from diegosouzapw/awesome-omni-skill

全面的AB测试分析工具,支持实验设计、统计检验、用户分群分析和可视化报告生成。用于分析产品改版、营销活动、功能优化等AB测试结果,提供统计显著性检验和深度洞察。

cli-e2e-testing

16
from diegosouzapw/awesome-omni-skill

CLI E2E testing patterns with BATS - parallelization, state sharing, and timeout management

bats-testing-patterns

16
from diegosouzapw/awesome-omni-skill

Comprehensive guide for writing shell script tests using Bats (Bash Automated Testing System). Use when writing or improving tests for Bash/shell scripts, creating test fixtures, mocking commands, or setting up CI/CD for shell script testing. Includes patterns for assertions, setup/teardown, mocking, fixtures, and integration with GitHub Actions.

adb-device-testing

16
from diegosouzapw/awesome-omni-skill

Use when testing Android apps on ADB-connected devices/emulators - UI automation, screenshots, location spoofing, navigation, app management. Triggers on ADB, emulator, Android testing, location mock, UI test, screenshot walkthrough.

sqlmap-database-pentesting

16
from diegosouzapw/awesome-omni-skill

This skill should be used when the user asks to "automate SQL injection testing," "enumerate database structure," "extract database credentials using sqlmap," "dump tables and columns...

sql-injection-testing

16
from diegosouzapw/awesome-omni-skill

This skill should be used when the user asks to "test for SQL injection vulnerabilities", "perform SQLi attacks", "bypass authentication using SQL injection", "extract database inform...

Contract Testing Pact

16
from diegosouzapw/awesome-omni-skill

Contract testing validates that service consumers and providers agree on request/response expectations. Pact implements consumer-driven contracts (CDC) with shareable pact files and provider verificat

Async Testing Expert

16
from diegosouzapw/awesome-omni-skill

Comprehensive pytest skill for async Python testing with proper mocking, fixtures, and patterns from production-ready test suites. Use when writing or improving async tests for Python applications, especially FastAPI backends with database interactions.

api-testing-suite

16
from diegosouzapw/awesome-omni-skill

Validate API responses and schemas.

api-testing-patterns

16
from diegosouzapw/awesome-omni-skill

Comprehensive API testing patterns including contract testing, REST/GraphQL testing, and integration testing. Use when testing APIs or designing API test strategies.

api-testing-observability-api-mock

16
from diegosouzapw/awesome-omni-skill

You are an API mocking expert specializing in realistic mock services for development, testing, and demos. Design mocks that simulate real API behavior and enable parallel development.