Skip to content
Back to skills

Configure Integration Tests

ASecurity

Check and configure integration testing for services, databases, and external dependencies

  • 58 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 8, 2026
testingjavascripttypescriptpythonrustgojavashellbashsqlnode

Works with

  • cli
  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add laurigates/claude-plugins --skill configure-integration-tests --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Configure Integration Tests?

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

Security grade badge for Configure Integration Tests
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/laurigates-configure-integration-tests/badge)](https://www.skillsdirectory.com/skills/laurigates-configure-integration-tests)

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
---
model: haiku
created: 2025-12-16
modified: 2025-12-16
reviewed: 2025-12-16
description: Check and configure integration testing for services, databases, and external dependencies
allowed-tools: Glob, Grep, Read, Write, Edit, Bash, AskUserQuestion, TodoWrite
argument-hint: "[--check-only] [--fix] [--framework <supertest|pytest|testcontainers>]"
name: configure-integration-tests
---

# /configure:integration-tests

Check and configure integration testing infrastructure for testing service interactions, databases, and external dependencies.

## Context

This command validates integration testing setup and optionally configures frameworks for testing real service interactions (as opposed to unit tests with mocks or E2E browser tests).

**Integration Testing Stack by Language:**
- **JavaScript/TypeScript**: Supertest + Testcontainers
- **Python**: pytest + testcontainers-python + httpx
- **Rust**: cargo test with `#[ignore]` + testcontainers-rs
- **Go**: testing + testcontainers-go

**Key Difference from Unit Tests:**
- Integration tests interact with **real** databases, APIs, and services
- They test **component boundaries** and **data flow**
- They typically require **test fixtures** and **cleanup**

## Workflow

### Phase 1: Project Detection

Detect existing integration testing infrastructure:

| Indicator | Component | Status |
|-----------|-----------|--------|
| `tests/integration/` directory | Integration tests | Present |
| `testcontainers` in dependencies | Container testing | Configured |
| `supertest` in package.json | HTTP testing | Configured |
| `docker-compose.test.yml` | Test services | Present |
| `pytest.ini` with `integration` marker | pytest integration | Configured |

### Phase 2: Current State Analysis

Check for complete integration testing setup:

**Test Organization:**
- [ ] `tests/integration/` directory exists
- [ ] Integration tests separated from unit tests
- [ ] Test fixtures and factories present
- [ ] Database seeding/migration scripts

**JavaScript/TypeScript (Supertest):**
- [ ] `supertest` installed
- [ ] `@testcontainers/postgresql` or similar installed
- [ ] Test database configuration
- [ ] API endpoint tests present
- [ ] Authentication test helpers

**Python (pytest + testcontainers):**
- [ ] `testcontainers` installed
- [ ] `httpx` or `requests` for HTTP testing
- [ ] `pytest-asyncio` for async tests
- [ ] `integration` marker defined
- [ ] Database fixtures in `conftest.py`

**Container Infrastructure:**
- [ ] `docker-compose.test.yml` exists
- [ ] Test database container defined
- [ ] Redis/cache container (if needed)
- [ ] Message queue container (if needed)
- [ ] Network isolation configured

### Phase 3: Compliance Report

Generate formatted compliance report:

```
Integration Testing Compliance Report
======================================
Project: [name]
Language: [TypeScript | Python | Rust | Go]

Test Organization:
  Integration directory    tests/integration/         [✅ EXISTS | ❌ MISSING]
  Separated from unit      not in src/                [✅ CORRECT | ⚠️ MIXED]
  Test fixtures            tests/fixtures/            [✅ EXISTS | ⚠️ MISSING]
  Database seeds           tests/seeds/               [✅ EXISTS | ⏭️ N/A]

Framework Setup:
  HTTP testing             supertest/httpx            [✅ INSTALLED | ❌ MISSING]
  Container testing        testcontainers             [✅ INSTALLED | ⚠️ MISSING]
  Async support            pytest-asyncio             [✅ INSTALLED | ⏭️ N/A]

Infrastructure:
  docker-compose.test.yml  test services              [✅ EXISTS | ⚠️ MISSING]
  Test database            PostgreSQL/SQLite          [✅ CONFIGURED | ❌ MISSING]
  Service isolation        network config             [✅ CONFIGURED | ⚠️ MISSING]

CI/CD Integration:
  Integration test job     GitHub Actions             [✅ CONFIGURED | ❌ MISSING]
  Service containers       workflow services          [✅ CONFIGURED | ⚠️ MISSING]
  Parallel execution       matrix strategy            [✅ CONFIGURED | ⏭️ OPTIONAL]

Overall: [X issues found]

Recommendations:
  - Install testcontainers for database testing
  - Create docker-compose.test.yml for local testing
  - Add integration test job to CI workflow
```

### Phase 4: Configuration (if --fix or user confirms)

#### JavaScript/TypeScript Setup

**Install dependencies:**
```bash
bun add --dev supertest @types/supertest
bun add --dev @testcontainers/postgresql
bun add --dev testcontainers
```

**Create `tests/integration/setup.ts`:**
```typescript
import { PostgreSqlContainer, StartedPostgreSqlContainer } from '@testcontainers/postgresql';
import { afterAll, beforeAll } from 'vitest';

let postgresContainer: StartedPostgreSqlContainer;

export async function setupTestDatabase(): Promise<string> {
  postgresContainer = await new PostgreSqlContainer('postgres:16-alpine')
    .withDatabase('test_db')
    .withUsername('test')
    .withPassword('test')
    .start();

  return postgresContainer.getConnectionUri();
}

export async function teardownTestDatabase(): Promise<void> {
  if (postgresContainer) {
    await postgresContainer.stop();
  }
}

// Global setup for all integration tests
beforeAll(async () => {
  const connectionUri = await setupTestDatabase();
  process.env.DATABASE_URL = connectionUri;
}, 60000); // 60s timeout for container startup

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

**Create `tests/integration/api.test.ts`:**
```typescript
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import { app } from '../../src/app'; // Your Express/Fastify app
import './setup'; // Import container setup

describe('API Integration Tests', () => {
  describe('GET /api/users', () => {
    it('should return empty array when no users exist', async () => {
      const response = await request(app)
        .get('/api/users')
        .expect('Content-Type', /json/)
        .expect(200);

      expect(response.body).toEqual([]);
    });

    it('should return users after creation', async () => {
      // Create a user
      await request(app)
        .post('/api/users')
        .send({ name: 'Test User', email: 'test@example.com' })
        .expect(201);

      // Fetch users
      const response = await request(app)
        .get('/api/users')
        .expect(200);

      expect(response.body).toHaveLength(1);
      expect(response.body[0].name).toBe('Test User');
    });
  });

  describe('Authentication Flow', () => {
    it('should register and login user', async () => {
      // Register
      const registerResponse = await request(app)
        .post('/api/auth/register')
        .send({
          email: 'newuser@example.com',
          password: 'securepassword123',
        })
        .expect(201);

      expect(registerResponse.body).toHaveProperty('token');

      // Login
      const loginResponse = await request(app)
        .post('/api/auth/login')
        .send({
          email: 'newuser@example.com',
          password: 'securepassword123',
        })
        .expect(200);

      expect(loginResponse.body).toHaveProperty('token');
    });
  });
});
```

**Create `tests/integration/database.test.ts`:**
```typescript
import { describe, it, expect, beforeEach } from 'vitest';
import { db } from '../../src/db'; // Your database client
import './setup';

describe('Database Integration Tests', () => {
  beforeEach(async () => {
    // Clean up before each test
    await db.query('TRUNCATE users CASCADE');
  });

  it('should insert and retrieve user', async () => {
    const result = await db.query(
      'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
      ['Test User', 'test@example.com']
    );

    expect(result.rows[0]).toMatchObject({
      name: 'Test User',
      email: 'test@example.com',
    });

    const fetchResult = await db.query('SELECT * FROM users WHERE id = $1', [
      result.rows[0].id,
    ]);

    expect(fetchResult.rows[0].name).toBe('Test User');
  });

  it('should enforce unique email constraint', async () => {
    await db.query(
      'INSERT INTO users (name, email) VALUES ($1, $2)',
      ['User 1', 'duplicate@example.com']
    );

    await expect(
      db.query(
        'INSERT INTO users (name, email) VALUES ($1, $2)',
        ['User 2', 'duplicate@example.com']
      )
    ).rejects.toThrow(/unique constraint/i);
  });
});
```

#### Python Setup

**Install dependencies:**
```bash
uv add --group dev testcontainers httpx pytest-asyncio
```

**Update `pyproject.toml`:**
```toml
[tool.pytest.ini_options]
markers = [
    "unit: Unit tests (fast, no external dependencies)",
    "integration: Integration tests (require services/containers)",
    "e2e: End-to-end tests (full system)",
    "slow: Slow running tests",
]

# Default to running unit tests only
addopts = "-m 'not integration and not e2e'"

[tool.pytest.ini_options.integration]
# Run with: pytest -m integration
addopts = "-m integration --tb=short"
```

**Create `tests/integration/conftest.py`:**
```python
import pytest
from testcontainers.postgres import PostgresContainer
from httpx import AsyncClient
import asyncio

@pytest.fixture(scope="session")
def event_loop():
    """Create event loop for async tests."""
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()

@pytest.fixture(scope="session")
def postgres_container():
    """Start PostgreSQL container for integration tests."""
    with PostgresContainer("postgres:16-alpine") as postgres:
        yield postgres

@pytest.fixture(scope="session")
def database_url(postgres_container):
    """Get database URL from container."""
    return postgres_container.get_connection_url()

@pytest.fixture
async def db_session(database_url):
    """Create database session with automatic cleanup."""
    from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
    from sqlalchemy.orm import sessionmaker

    # Convert to async URL
    async_url = database_url.replace("postgresql://", "postgresql+asyncpg://")
    engine = create_async_engine(async_url)

    async_session = sessionmaker(
        engine, class_=AsyncSession, expire_on_commit=False
    )

    async with async_session() as session:
        yield session
        await session.rollback()

@pytest.fixture
async def api_client(database_url):
    """Create test client for API."""
    import os
    os.environ["DATABASE_URL"] = database_url

    from app.main import app  # Your FastAPI/Flask app

    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client
```

**Create `tests/integration/test_api.py`:**
```python
import pytest
from httpx import AsyncClient

pytestmark = pytest.mark.integration

@pytest.mark.asyncio
async def test_create_user(api_client: AsyncClient):
    """Test user creation through API."""
    response = await api_client.post(
        "/api/users",
        json={"name": "Test User", "email": "test@example.com"},
    )

    assert response.status_code == 201
    data = response.json()
    assert data["name"] == "Test User"
    assert "id" in data

@pytest.mark.asyncio
async def test_get_users(api_client: AsyncClient):
    """Test fetching users list."""
    # Create a user first
    await api_client.post(
        "/api/users",
        json={"name": "Test User", "email": "test@example.com"},
    )

    response = await api_client.get("/api/users")

    assert response.status_code == 200
    data = response.json()
    assert len(data) >= 1

@pytest.mark.asyncio
async def test_authentication_flow(api_client: AsyncClient):
    """Test complete auth flow: register -> login -> access protected."""
    # Register
    register_response = await api_client.post(
        "/api/auth/register",
        json={"email": "newuser@example.com", "password": "secure123"},
    )
    assert register_response.status_code == 201

    # Login
    login_response = await api_client.post(
        "/api/auth/login",
        json={"email": "newuser@example.com", "password": "secure123"},
    )
    assert login_response.status_code == 200
    token = login_response.json()["token"]

    # Access protected endpoint
    protected_response = await api_client.get(
        "/api/profile",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert protected_response.status_code == 200
```

#### Docker Compose Test Configuration

**Create `docker-compose.test.yml`:**
```yaml
version: '3.8'

services:
  test-db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test
      POSTGRES_DB: test_db
    ports:
      - "5433:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U test -d test_db"]
      interval: 5s
      timeout: 5s
      retries: 5
    tmpfs:
      - /var/lib/postgresql/data  # Use tmpfs for faster tests

  test-redis:
    image: redis:7-alpine
    ports:
      - "6380:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5

  # Optional: Message queue for event-driven tests
  test-rabbitmq:
    image: rabbitmq:3-alpine
    ports:
      - "5673:5672"
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "check_running"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  default:
    name: integration-test-network
```

**Add npm scripts to `package.json`:**
```json
{
  "scripts": {
    "test:integration": "vitest run --config vitest.integration.config.ts",
    "test:integration:watch": "vitest --config vitest.integration.config.ts",
    "test:integration:docker": "docker compose -f docker-compose.test.yml up -d && npm run test:integration && docker compose -f docker-compose.test.yml down",
    "docker:test:up": "docker compose -f docker-compose.test.yml up -d",
    "docker:test:down": "docker compose -f docker-compose.test.yml down -v"
  }
}
```

**Create `vitest.integration.config.ts`:**
```typescript
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    include: ['tests/integration/**/*.test.ts'],
    setupFiles: ['tests/integration/setup.ts'],
    testTimeout: 30000, // 30s for container operations
    hookTimeout: 60000, // 60s for container startup
    pool: 'forks', // Use forks for isolation
    poolOptions: {
      forks: {
        singleFork: true, // Run sequentially to avoid port conflicts
      },
    },
    env: {
      NODE_ENV: 'test',
    },
  },
});
```

### Phase 5: CI/CD Integration

**Add to `.github/workflows/test.yml`:**

```yaml
jobs:
  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile
      - run: bun test

  integration-tests:
    runs-on: ubuntu-latest
    needs: unit-tests  # Run after unit tests pass

    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
          POSTGRES_DB: test_db
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

      redis:
        image: redis:7-alpine
        ports:
          - 6379:6379
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2

      - name: Install dependencies
        run: bun install --frozen-lockfile

      - name: Run database migrations
        run: bun run db:migrate
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/test_db

      - name: Run integration tests
        run: bun run test:integration
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/test_db
          REDIS_URL: redis://localhost:6379

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: integration-test-results
          path: test-results/
```

### Phase 6: Test Fixtures and Factories

**Create `tests/fixtures/factories.ts`:**
```typescript
import { faker } from '@faker-js/faker';

export interface UserFactory {
  name: string;
  email: string;
  password?: string;
}

export function createUserData(overrides: Partial<UserFactory> = {}): UserFactory {
  return {
    name: faker.person.fullName(),
    email: faker.internet.email(),
    password: faker.internet.password({ length: 12 }),
    ...overrides,
  };
}

export function createManyUsers(count: number, overrides: Partial<UserFactory> = {}): UserFactory[] {
  return Array.from({ length: count }, () => createUserData(overrides));
}

// Database seeding helper
export async function seedDatabase(db: any) {
  const users = createManyUsers(10);

  for (const user of users) {
    await db.query(
      'INSERT INTO users (name, email) VALUES ($1, $2)',
      [user.name, user.email]
    );
  }

  return users;
}
```

### Phase 7: Standards Tracking

Update `.project-standards.yaml`:

```yaml
standards_version: "2025.1"
last_configured: "[timestamp]"
components:
  integration_tests: "2025.1"
  integration_tests_framework: "[supertest|pytest|testcontainers]"
  integration_tests_containers: true
  integration_tests_ci: true
```

### Phase 8: Updated Compliance Report

```
Integration Testing Configuration Complete
===========================================

Framework: Supertest + Testcontainers
Language: TypeScript

Configuration Applied:
  ✅ supertest installed for HTTP testing
  ✅ testcontainers installed for database containers
  ✅ tests/integration/ directory created
  ✅ vitest.integration.config.ts created

Test Infrastructure:
  ✅ Container setup with PostgreSQL
  ✅ Database cleanup between tests
  ✅ Test fixtures and factories

Scripts Added:
  ✅ bun run test:integration (run tests)
  ✅ bun run test:integration:watch (watch mode)
  ✅ bun run test:integration:docker (with docker-compose)

CI/CD:
  ✅ Integration test job added to workflow
  ✅ Service containers configured
  ✅ Runs after unit tests pass

Next Steps:
  1. Start test containers:
     bun run docker:test:up

  2. Run integration tests:
     bun run test:integration

  3. Stop containers:
     bun run docker:test:down

  4. Run full suite with containers:
     bun run test:integration:docker

Documentation:
  - Supertest: https://github.com/ladjs/supertest
  - Testcontainers: https://testcontainers.com
```

## Flags

| Flag | Description |
|------|-------------|
| `--check-only` | Report status without offering fixes |
| `--fix` | Apply all fixes automatically without prompting |
| `--framework <framework>` | Override framework detection (supertest, pytest, testcontainers) |

## Examples

```bash
# Check compliance and offer fixes
/configure:integration-tests

# Check only, no modifications
/configure:integration-tests --check-only

# Auto-fix all issues
/configure:integration-tests --fix

# Force specific framework
/configure:integration-tests --fix --framework pytest
```

## Error Handling

- **No app entry point found**: Ask user to specify app location
- **Docker not available**: Warn about testcontainers requirement
- **Database type unknown**: Ask user to specify database type
- **Port conflicts**: Suggest alternative ports in docker-compose

## See Also

- `/configure:tests` - Unit testing configuration
- `/configure:api-tests` - API contract testing
- `/configure:coverage` - Coverage configuration
- `/configure:all` - Run all compliance checks
- **Testcontainers documentation**: https://testcontainers.com
- **Supertest documentation**: https://github.com/ladjs/supertest

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.