Skip to content
Back to skills

Integration Test Writer

ASecurity

Generate comprehensive integration tests for component interactions,

  • 666 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added February 9, 2026
testingjavascripttypescriptpythonjavabashsqlexpressfastapitestingapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill integration-test-writer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Integration Test Writer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Integration Test Writer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-integration-test-writer/badge)](https://www.skillsdirectory.com/skills/majiayu000-integration-test-writer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: integration-test-writer
description: Generate comprehensive integration tests for component interactions,
  workflows, and system boundaries. Use for testing API endpoints, database operations,
  and multi-component flows.
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
---

# Integration Test Writer Skill

## Purpose

This skill provides systematic guidance for writing integration tests that verify component interactions, API endpoints, database operations, and end-to-end workflows. Integration tests validate that multiple components work together correctly.

## When to Use

- Test API endpoints and routes
- Verify database interactions
- Test multi-component workflows
- Validate authentication and authorization flows
- Test external service integrations
- Verify error handling across boundaries

## Integration vs Unit Testing

**Unit Tests:**
- Test single component in isolation
- Mock all dependencies
- Fast execution (< 1 second)
- High coverage of edge cases

**Integration Tests:**
- Test multiple components together
- Use real or test doubles (minimal mocking)
- Slower execution (seconds to minutes)
- Focus on component interactions

---

## Integration Testing Workflow

### 1. Identify Integration Points

**Map the system:**
```bash
# Identify components to test together
- API controllers + Services + Database
- Services + External APIs
- Authentication + Authorization + Resources
- Multi-step workflows
```

**Integration test targets:**
- [ ] API endpoints (all HTTP methods)
- [ ] Database CRUD operations
- [ ] Authentication flows
- [ ] Authorization checks
- [ ] External service calls
- [ ] Multi-component workflows
- [ ] Error propagation across boundaries

**Deliverable:** Integration test plan

---

### 2. Setup Test Environment

**Test environment components:**

1. **Test Database:**
   - Separate database for testing
   - Reset between tests
   - Seed data for tests

2. **Test Configuration:**
   - Override production settings
   - Use test credentials
   - Mock external services

3. **Test Fixtures:**
   - Factory functions for test data
   - Reusable setup/teardown
   - Consistent test state

**Python example (pytest + FastAPI):**

```python
# tests/conftest.py
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session

from src.main import app
from src.database import Base, get_db
from src.models import User, Resource

# Test database
TEST_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(TEST_DATABASE_URL, connect_args={"check_same_thread": False})
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


@pytest.fixture(scope="function")
def db() -> Session:
    """
    Database fixture with setup and teardown.

    Yields:
        Database session for testing

    Notes:
        - Creates all tables before test
        - Drops all tables after test
        - Each test gets fresh database
    """
    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: Session) -> TestClient:
    """
    Test client with database dependency override.

    Args:
        db: Database session fixture

    Returns:
        FastAPI TestClient configured for testing
    """
    def override_get_db():
        try:
            yield db
        finally:
            pass

    app.dependency_overrides[get_db] = override_get_db
    client = TestClient(app)
    yield client
    app.dependency_overrides.clear()


@pytest.fixture
def test_user(db: Session) -> User:
    """
    Create test user in database.

    Args:
        db: Database session

    Returns:
        Created user instance
    """
    user = User(
        name="Test User",
        email="test@example.com",
        password_hash="hashed_password"
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    return user


@pytest.fixture
def auth_token(client: TestClient, test_user: User) -> str:
    """
    Generate authentication token for test user.

    Args:
        client: Test client
        test_user: Test user fixture

    Returns:
        JWT authentication token
    """
    response = client.post(
        "/api/auth/login",
        json={"email": test_user.email, "password": "password"}
    )
    return response.json()["access_token"]


@pytest.fixture
def auth_headers(auth_token: str) -> dict:
    """
    Generate authorization headers with token.

    Args:
        auth_token: JWT token

    Returns:
        Headers dictionary with Authorization header
    """
    return {"Authorization": f"Bearer {auth_token}"}
```

**JavaScript/TypeScript example (Jest + Express):**

```typescript
// tests/setup.ts
import { Express } from 'express';
import request from 'supertest';
import { createApp } from '../src/app';
import { setupTestDatabase, teardownTestDatabase } from './helpers/database';

let app: Express;

beforeAll(async () => {
  await setupTestDatabase();
  app = createApp();
});

afterAll(async () => {
  await teardownTestDatabase();
});

beforeEach(async () => {
  // Clean database before each test
  await clearDatabase();
});

export const getTestApp = () => app;

// tests/helpers/database.ts
import { DataSource } from 'typeorm';

let testDataSource: DataSource;

export async function setupTestDatabase() {
  testDataSource = new DataSource({
    type: 'sqlite',
    database: ':memory:',
    entities: ['src/entities/**/*.ts'],
    synchronize: true,
  });

  await testDataSource.initialize();
}

export async function teardownTestDatabase() {
  await testDataSource.destroy();
}

export async function clearDatabase() {
  const entities = testDataSource.entityMetadatas;
  for (const entity of entities) {
    const repository = testDataSource.getRepository(entity.name);
    await repository.clear();
  }
}
```

**Deliverable:** Test environment configured

---

### 3. Write API Integration Tests

**Test structure for API endpoints:**

```python
# tests/integration/test_users_api.py
"""
Integration tests for Users API.

Tests cover:
- CRUD operations
- Authentication and authorization
- Validation and error handling
- Database interactions
"""

import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session

from src.models import User


class TestUsersAPI:
    """Tests for /api/users endpoints."""

    def test_get_users_returns_list(self, client: TestClient, db: Session):
        """Test GET /api/users returns list of users."""
        # Arrange: Create test users
        users = [
            User(name=f"User {i}", email=f"user{i}@example.com")
            for i in range(3)
        ]
        db.add_all(users)
        db.commit()

        # Act
        response = client.get("/api/users")

        # Assert
        assert response.status_code == 200
        data = response.json()
        assert len(data) == 3
        assert all("id" in user for user in data)
        assert all("name" in user for user in data)

    def test_get_user_by_id_returns_user(
        self, client: TestClient, test_user: User
    ):
        """Test GET /api/users/:id returns specific user."""
        # Act
        response = client.get(f"/api/users/{test_user.id}")

        # Assert
        assert response.status_code == 200
        data = response.json()
        assert data["id"] == test_user.id
        assert data["name"] == test_user.name
        assert data["email"] == test_user.email

    def test_get_user_nonexistent_returns_404(self, client: TestClient):
        """Test GET /api/users/:id with invalid ID returns 404."""
        # Act
        response = client.get("/api/users/99999")

        # Assert
        assert response.status_code == 404
        assert "not found" in response.json()["detail"].lower()

    def test_create_user_returns_created(
        self, client: TestClient, db: Session
    ):
        """Test POST /api/users creates new user."""
        # Arrange
        user_data = {
            "name": "New User",
            "email": "newuser@example.com",
            "password": "SecurePass123"
        }

        # Act
        response = client.post("/api/users", json=user_data)

        # Assert
        assert response.status_code == 201
        data = response.json()
        assert data["name"] == user_data["name"]
        assert data["email"] == user_data["email"]
        assert "id" in data
        assert "password" not in data  # Password not returned

        # Verify in database
        user = db.query(User).filter_by(email=user_data["email"]).first()
        assert user is not None
        assert user.name == user_data["name"]

    def test_create_user_duplicate_email_returns_400(
        self, client: TestClient, test_user: User
    ):
        """Test POST /api/users with duplicate email returns 400."""
        # Arrange
        duplicate_data = {
            "name": "Another User",
            "email": test_user.email,
            "password": "password"
        }

        # Act
        response = client.post("/api/users", json=duplicate_data)

        # Assert
        assert response.status_code == 400
        assert "email" in response.json()["detail"].lower()

    def test_create_user_invalid_email_returns_400(self, client: TestClient):
        """Test POST /api/users with invalid email returns 400."""
        # Arrange
        invalid_data = {
            "name": "User",
            "email": "not-an-email",
            "password": "password"
        }

        # Act
        response = client.post("/api/users", json=invalid_data)

        # Assert
        assert response.status_code == 400

    def test_update_user_returns_updated(
        self, client: TestClient, test_user: User, auth_headers: dict, db: Session
    ):
        """Test PUT /api/users/:id updates user."""
        # Arrange
        update_data = {"name": "Updated Name"}

        # Act
        response = client.put(
            f"/api/users/{test_user.id}",
            json=update_data,
            headers=auth_headers
        )

        # Assert
        assert response.status_code == 200
        data = response.json()
        assert data["name"] == "Updated Name"

        # Verify in database
        db.refresh(test_user)
        assert test_user.name == "Updated Name"

    def test_update_user_without_auth_returns_401(
        self, client: TestClient, test_user: User
    ):
        """Test PUT /api/users/:id without auth returns 401."""
        # Arrange
        update_data = {"name": "Updated Name"}

        # Act
        response = client.put(
            f"/api/users/{test_user.id}",
            json=update_data
        )

        # Assert
        assert response.status_code == 401

    def test_delete_user_returns_no_content(
        self, client: TestClient, test_user: User, auth_headers: dict, db: Session
    ):
        """Test DELETE /api/users/:id deletes user."""
        # Act
        response = client.delete(
            f"/api/users/{test_user.id}",
            headers=auth_headers
        )

        # Assert
        assert response.status_code == 204

        # Verify in database
        deleted_user = db.query(User).filter_by(id=test_user.id).first()
        assert deleted_user is None
```

**Deliverable:** API integration tests

---

### 4. Write Database Integration Tests

**Test database operations:**

```python
# tests/integration/test_user_repository.py
"""
Integration tests for User repository database operations.
"""

import pytest
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError

from src.models import User
from src.repositories import UserRepository


class TestUserRepository:
    """Tests for UserRepository database operations."""

    @pytest.fixture
    def repository(self, db: Session) -> UserRepository:
        """Create repository instance."""
        return UserRepository(db)

    def test_create_user_saves_to_database(
        self, repository: UserRepository, db: Session
    ):
        """Test create saves user to database."""
        # Arrange
        user_data = {
            "name": "Test User",
            "email": "test@example.com",
            "password": "password"
        }

        # Act
        user = repository.create(user_data)

        # Assert
        assert user.id is not None

        # Verify in database
        saved_user = db.query(User).filter_by(id=user.id).first()
        assert saved_user is not None
        assert saved_user.name == user_data["name"]

    def test_create_duplicate_email_raises_error(
        self, repository: UserRepository
    ):
        """Test creating user with duplicate email raises error."""
        # Arrange
        user_data = {"name": "User", "email": "test@example.com"}
        repository.create(user_data)

        # Act & Assert
        with pytest.raises(IntegrityError):
            repository.create(user_data)

    def test_find_by_id_returns_user(
        self, repository: UserRepository, test_user: User
    ):
        """Test find_by_id returns correct user."""
        # Act
        user = repository.find_by_id(test_user.id)

        # Assert
        assert user is not None
        assert user.id == test_user.id
        assert user.email == test_user.email

    def test_find_by_email_returns_user(
        self, repository: UserRepository, test_user: User
    ):
        """Test find_by_email returns correct user."""
        # Act
        user = repository.find_by_email(test_user.email)

        # Assert
        assert user is not None
        assert user.id == test_user.id

    def test_update_modifies_user(
        self, repository: UserRepository, test_user: User, db: Session
    ):
        """Test update modifies user in database."""
        # Arrange
        update_data = {"name": "Updated Name"}

        # Act
        updated_user = repository.update(test_user.id, update_data)

        # Assert
        assert updated_user.name == "Updated Name"

        # Verify in database
        db.refresh(test_user)
        assert test_user.name == "Updated Name"

    def test_delete_removes_user(
        self, repository: UserRepository, test_user: User, db: Session
    ):
        """Test delete removes user from database."""
        # Act
        repository.delete(test_user.id)

        # Assert - Verify removed from database
        deleted_user = db.query(User).filter_by(id=test_user.id).first()
        assert deleted_user is None
```

**Deliverable:** Database integration tests

---

### 5. Write Multi-Component Workflow Tests

**Test end-to-end workflows:**

```python
# tests/integration/test_user_workflows.py
"""
Integration tests for user-related workflows.
"""

import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session

from src.models import User, EmailVerification


class TestUserRegistrationWorkflow:
    """Tests for complete user registration workflow."""

    def test_complete_registration_flow(
        self, client: TestClient, db: Session
    ):
        """Test complete user registration and verification flow."""
        # Step 1: Register new user
        register_data = {
            "name": "New User",
            "email": "newuser@example.com",
            "password": "SecurePass123"
        }
        response = client.post("/api/register", json=register_data)

        assert response.status_code == 201
        user_data = response.json()
        user_id = user_data["id"]
        assert user_data["email_verified"] is False

        # Step 2: Verify email verification record created
        verification = db.query(EmailVerification).filter_by(
            user_id=user_id
        ).first()
        assert verification is not None
        assert verification.is_used is False

        # Step 3: Verify email with token
        verify_response = client.post(
            "/api/verify-email",
            json={"token": verification.token}
        )
        assert verify_response.status_code == 200

        # Step 4: Verify user is now verified
        user = db.query(User).filter_by(id=user_id).first()
        assert user.email_verified is True

        # Step 5: Verify can login
        login_response = client.post(
            "/api/login",
            json={
                "email": register_data["email"],
                "password": register_data["password"]
            }
        )
        assert login_response.status_code == 200
        assert "access_token" in login_response.json()

        # Step 6: Access protected resource with token
        token = login_response.json()["access_token"]
        headers = {"Authorization": f"Bearer {token}"}
        profile_response = client.get("/api/profile", headers=headers)

        assert profile_response.status_code == 200
        profile = profile_response.json()
        assert profile["email"] == register_data["email"]
        assert profile["email_verified"] is True
```

**Deliverable:** Workflow integration tests

---

### 6. Test Authentication & Authorization

**Authentication tests:**

```python
class TestAuthentication:
    """Tests for authentication flows."""

    def test_login_valid_credentials_returns_token(
        self, client: TestClient, test_user: User
    ):
        """Test login with valid credentials returns token."""
        # Arrange
        login_data = {
            "email": test_user.email,
            "password": "password"  # Assuming test_user has this password
        }

        # Act
        response = client.post("/api/login", json=login_data)

        # Assert
        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        assert "token_type" in data
        assert data["token_type"] == "bearer"

    def test_login_invalid_password_returns_401(
        self, client: TestClient, test_user: User
    ):
        """Test login with invalid password returns 401."""
        # Arrange
        login_data = {
            "email": test_user.email,
            "password": "wrong_password"
        }

        # Act
        response = client.post("/api/login", json=login_data)

        # Assert
        assert response.status_code == 401

    def test_protected_endpoint_without_token_returns_401(
        self, client: TestClient
    ):
        """Test protected endpoint without token returns 401."""
        # Act
        response = client.get("/api/profile")

        # Assert
        assert response.status_code == 401

    def test_protected_endpoint_with_valid_token_returns_data(
        self, client: TestClient, auth_headers: dict
    ):
        """Test protected endpoint with valid token returns data."""
        # Act
        response = client.get("/api/profile", headers=auth_headers)

        # Assert
        assert response.status_code == 200


class TestAuthorization:
    """Tests for authorization checks."""

    def test_admin_endpoint_with_admin_user_succeeds(
        self, client: TestClient, admin_user: User, admin_headers: dict
    ):
        """Test admin endpoint allows admin user."""
        # Act
        response = client.get("/api/admin/users", headers=admin_headers)

        # Assert
        assert response.status_code == 200

    def test_admin_endpoint_with_regular_user_returns_403(
        self, client: TestClient, test_user: User, auth_headers: dict
    ):
        """Test admin endpoint denies regular user."""
        # Act
        response = client.get("/api/admin/users", headers=auth_headers)

        # Assert
        assert response.status_code == 403
```

**Deliverable:** Auth/authz integration tests

---

## Best Practices

1. **Use test database:** Separate from dev/production
2. **Reset state:** Clean database between tests
3. **Test real interactions:** Use actual database, minimal mocking
4. **Test both paths:** Success and error scenarios
5. **Verify side effects:** Check database, logs, notifications
6. **Test security:** Authentication and authorization
7. **Test transactions:** Ensure atomicity and rollback
8. **Keep tests focused:** One workflow or integration per test
9. **Use factories:** Consistent test data creation
10. **Document contracts:** Tests show API usage

---

## Running Integration Tests

```bash
# Python (pytest)
pytest tests/integration/ -v
pytest tests/integration/test_api.py -v
pytest tests/integration/ -v --cov=src

# JavaScript/TypeScript (Jest)
npm run test:integration
jest tests/integration/**/*.test.ts --coverage

# Run with test database
DATABASE_URL=sqlite:///./test.db pytest tests/integration/
```

---

## Quality Checklist

Before completing integration tests:

- [ ] All API endpoints tested
- [ ] CRUD operations verified
- [ ] Authentication tested
- [ ] Authorization tested
- [ ] Error handling validated
- [ ] Database state verified
- [ ] Multi-component workflows tested
- [ ] Tests are isolated and independent
- [ ] Test database separate from dev
- [ ] All tests pass
- [ ] Performance acceptable (< 5 minutes)

---

## Integration with Testing Workflow

**Input:** System components to test together
**Process:** Setup → Test interactions → Verify → Cleanup
**Output:** Integration test suite validating component interactions
**Next Step:** End-to-end testing or deployment

---

## Remember

- **Test component interactions**, not isolated units
- **Use real database** (test instance)
- **Mock only external services** (APIs, third-party)
- **Verify database state** after operations
- **Test authentication and authorization flows**
- **Test both success and error paths**
- **Keep tests isolated** with cleanup between tests
- **Tests should be deterministic** and repeatable

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.