Claude Skills Guide

Claude Code Skills for Writing Integration Tests

Integration tests verify that different components of your application work together correctly. Unlike unit tests that isolate individual functions, integration tests exercise real workflows across modules, databases, APIs, and external services. Claude Code offers several skills that accelerate writing and maintaining integration tests, making your test suite more reliable and easier to maintain. For an overview of the testing ecosystem, visit the tutorials hub.

Why Integration Tests Matter

Integration tests catch bugs that unit tests miss. When your code interacts with databases, third-party APIs, or internal services, unit tests cannot verify these interactions work correctly. Integration tests validate the actual behavior of your system end-to-end, catching issues like incorrect SQL queries, malformed API responses, authentication failures, and timing issues.

However, integration tests present unique challenges. They require realistic test data, proper setup and teardown, and careful management of external dependencies. Claude Code skills help address these challenges by providing structured workflows and best practices.

Key Claude Code Skills for Integration Testing

The TDD Skill

The TDD skill provides a test-driven development workflow that works well for integration tests. When you activate this skill, Claude guides you through writing tests before implementation, ensuring your code meets requirements from the start.

Activate the skill in your Claude Code session:

/tdd

Then describe your integration scenario:

Write integration tests for the user authentication flow that tests 
registration, login, password reset, and session management against 
our PostgreSQL database.

The TDD skill generates test cases covering happy paths and edge cases, organizes test data appropriately, and ensures your tests properly clean up after themselves.

Integration Test Design Principles

Effective integration tests follow consistent design principles. Use these in your prompts to Claude Code to guide test generation:

Reviewing Integration Test Quality

After writing integration tests, ask Claude Code to review your test code:

Review these integration tests for common issues including missing edge cases, inadequate assertion coverage, improper test data management, and potential flakiness from timing dependencies.

## Practical Example: API Integration Tests

Consider a typical integration test scenario: testing a REST API endpoint that creates a user and returns the created record. Here is how Claude Code skills help structure these tests.

First, activate the TDD skill:

/tdd


Then describe your requirement:

Create integration tests for POST /api/users endpoint that validates input, creates a user record in PostgreSQL, and returns the created user with a 201 status code.


Claude generates a test file like this:

```python
import pytest
import requests
from unittest.mock import patch

BASE_URL = "http://localhost:8000"

class TestCreateUser:
    """Integration tests for user creation endpoint."""
    
    @pytest.fixture(autouse=True)
    def setup_and_teardown(self, test_db):
        """Ensure clean database state before each test."""
        test_db.clear_all_tables()
        yield
        test_db.clear_all_tables()
    
    def test_create_user_success(self, test_db, sample_user_data):
        """Test successful user creation returns 201 with user data."""
        response = requests.post(
            f"{BASE_URL}/api/users",
            json=sample_user_data
        )
        
        assert response.status_code == 201
        data = response.json()
        assert data["email"] == sample_user_data["email"]
        assert data["name"] == sample_user_data["name"]
        assert "id" in data
        assert "password" not in data  # Password not returned
        
        # Verify user exists in database
        user = test_db.get_user_by_email(sample_user_data["email"])
        assert user is not None
    
    def test_create_user_duplicate_email(self, test_db, sample_user_data):
        """Test that duplicate email returns 409 Conflict."""
        # Create initial user
        requests.post(f"{BASE_URL}/api/users", json=sample_user_data)
        
        # Attempt duplicate
        response = requests.post(
            f"{BASE_URL}/api/users",
            json=sample_user_data
        )
        
        assert response.status_code == 409
        assert "email" in response.json()["error"].lower()
    
    def test_create_user_invalid_email(self):
        """Test that invalid email returns 400 Bad Request."""
        invalid_data = {"email": "not-an-email", "name": "Test"}
        
        response = requests.post(
            f"{BASE_URL}/api/users",
            json=invalid_data
        )
        
        assert response.status_code == 400
    
    def test_create_user_missing_fields(self):
        """Test that missing required fields returns 422."""
        incomplete_data = {"email": "test@example.com"}
        
        response = requests.post(
            f"{BASE_URL}/api/users",
            json=incomplete_data
        )
        
        assert response.status_code == 422
        assert "name" in response.json()["error"]

Managing Test Data Effectively

One of the biggest challenges in integration testing is managing test data. Claude Code skills provide strategies for creating realistic, isolated test data. For a complete automated testing pipeline, see the automated testing pipeline guide.

Use Factories Instead of Fixtures

Rather than hardcoding test data in fixtures, use factory functions that generate unique data for each test:

@pytest.fixture
def sample_user_data():
    """Generate unique user data for each test."""
    return {
        "email": f"user_{uuid4()}@example.com",
        "name": f"Test User {uuid4().hex[:8]}",
        "password": "SecurePass123!"
    }

This approach prevents test pollution and ensures tests can run in parallel.

Clean State Between Tests

Integration tests require clean database state. Use database transactions that roll back after each test:

@pytest.fixture
def test_db(db_connection):
    """Provide database connection with automatic rollback."""
    connection = db_connection
    transaction = connection.begin()
    
    yield TestDatabase(connection)
    
    transaction.rollback()
    connection.close()

Testing External APIs

When your application depends on external APIs, use mocking to create reliable integration tests:

from unittest.mock import patch, Mock

@patch('app.services.payment_gateway.charge')
def test_payment_processing(mock_charge):
    """Test payment processing with mocked external API."""
    # Configure mock response
    mock_charge.return_value = {
        "id": "ch_123",
        "status": "succeeded",
        "amount": 5000
    }
    
    # Test your code
    result = process_payment(order_id=42, amount=5000)
    
    assert result["status"] == "completed"
    mock_charge.assert_called_once_with(amount=5000)

This approach tests your integration logic while keeping tests fast and reliable.

Best Practices Summary

Integration tests require different approaches than unit tests. Keep these principles in mind:

  1. Test real behavior, not implementation details — Focus on inputs and outputs rather than internal state
  2. Use realistic test data — Fake data that looks real catches more bugs
  3. Isolate tests from each other — Each test should clean up its own state
  4. Mock external services wisely — Mock at the right abstraction level
  5. Keep tests fast — Slow tests get ignored; aim for under one second per test
  6. Name tests descriptively — Test names should document the scenario being verified

Claude Code skills provide structured workflows for applying these practices. The TDD skill ensures tests are written first, and using Claude Code to review generated tests catches common mistakes before they become problems.


Built by theluckystrike — More at zovo.one