💻 Développement

dev-integration-test-builder

Crée des tests d'intégration pour vérifier l'interaction entre composants.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- dev-integration-test-builder --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } dev-integration-test-builder -Launch"

🚀 Déjà installé ?

claude "/dev-integration-test-builder"

Ou tapez /dev-integration-test-builder dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

test d'intégrationintegration testtester l'APItester la DBtest end-to-endtest E2ETestcontainersWebApplicationFactory

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/dev-integration-test-builder ~/.claude/skills/

Payload du plugin : skills/dev-integration-test-builder · source éditable : dev-skills/integration-test-builder

📖 Manuel

Integration Test Builder

Critères de décision : quel type de test choisir ?

ScénarioChoix recommandé
Controller + DB + auth sur vrai schémaWebApplicationFactory + Testcontainers
Microservice consommant une API tierceWireMock/MockServer + Testcontainers DB
Message broker (Kafka, RabbitMQ)Testcontainers (image officielle)
Lambda/Cloud Function légère, pas de DBBase in-memory + TestClient
Contrat entre deux microservicesPact (CDC)
Smoke test post-déploiementTest E2E contre l'environnement staging

Ne simuler avec un mock que ce qui est impossible ou coûteux à démarrer localement.


Workflow en étapes

1. Cartographier les points d'intégration

Lister explicitement :

Chaque point doit avoir au moins un scénario nominal et un scénario d'erreur.


2. Choisir et configurer l'infrastructure de test

Testcontainers — .NET (xUnit)

// NuGet : Testcontainers, Testcontainers.PostgreSql
public class PostgresFixture : IAsyncLifetime
{
    private readonly PostgreSqlContainer _db = new PostgreSqlBuilder()
        .WithImage("postgres:16-alpine")
        .Build();

    public string ConnectionString => _db.GetConnectionString();

    public Task InitializeAsync() => _db.StartAsync();
    public Task DisposeAsync() => _db.StopAsync();
}

Testcontainers — Node.js (Jest/Vitest)

// npm i testcontainers
import { PostgreSqlContainer } from "@testcontainers/postgresql";
let container: StartedPostgreSqlContainer;
beforeAll(async () => { container = await new PostgreSqlContainer().start(); });
afterAll(async () => { await container.stop(); });

Base in-memory (EF Core) — acceptable pour tests ultra-rapides uniquement

services.AddDbContext<AppDbContext>(o => o.UseInMemoryDatabase("test_" + Guid.NewGuid()));
// Attention : pas de contraintes FK, pas de SQL brut, pas de migrations.

3. Configurer le serveur de test

.NET — WebApplicationFactory

public class ApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
{
    private readonly PostgreSqlContainer _db = new PostgreSqlBuilder().Build();

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(services =>
        {
            // Remplacer la vraie connexion par celle du conteneur
            services.RemoveAll<DbContextOptions<AppDbContext>>();
            services.AddDbContext<AppDbContext>(o =>
                o.UseNpgsql(_db.GetConnectionString()));
        });
    }

    public async Task InitializeAsync() => await _db.StartAsync();
    public new async Task DisposeAsync() => await _db.StopAsync();
}

Python FastAPI

# pip install httpx pytest-asyncio
from httpx import AsyncClient, ASGITransport
import pytest

@pytest.fixture
async def client(db_session):  # db_session = session sur DB de test
    app.dependency_overrides[get_db] = lambda: db_session
    async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as c:
        yield c

Node.js / Express

// npm i supertest @types/supertest
import request from "supertest";
import { app } from "../src/app";

describe("POST /orders", () => {
  it("creates order and returns 201", async () => {
    const res = await request(app).post("/orders").send({ productId: 1, qty: 2 });
    expect(res.status).toBe(201);
    expect(res.body).toMatchObject({ id: expect.any(Number) });
  });
});

4. Fixtures et seed data

// Builder pattern C#
var user = new UserBuilder().WithRole("admin").WithEmail("test@example.com").Build();
await dbContext.Users.AddAsync(user);
await dbContext.SaveChangesAsync();
-- Rollback via transaction xUnit
// Utiliser Respawn (NuGet) pour un truncate rapide entre tests
var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions
{
    DbAdapter = DbAdapter.Postgres,
    SchemasToInclude = ["public"]
});
await respawner.ResetAsync(connection);

5. Écrire les scénarios d'intégration

Structure d'un test : Arrange → Act → Assert → Cleanup

[Fact]
public async Task CreateOrder_ValidPayload_Returns201AndPersists()
{
    // Arrange
    var client = _factory.CreateClient();
    var payload = new { productId = 42, quantity = 3 };

    // Act
    var response = await client.PostAsJsonAsync("/api/orders", payload);

    // Assert
    response.StatusCode.Should().Be(HttpStatusCode.Created);
    var body = await response.Content.ReadFromJsonAsync<OrderDto>();
    body!.Id.Should().BePositive();

    // Vérification en DB (pas seulement via l'API)
    using var scope = _factory.Services.CreateScope();
    var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    db.Orders.Should().ContainSingle(o => o.Id == body.Id);
}

Couvrir systématiquement :


6. Simuler les services externes

WireMock.Net (.NET)

// NuGet : WireMock.Net
var server = WireMockServer.Start();
server.Given(Request.Create().WithPath("/payments/charge").UsingPost())
      .RespondWith(Response.Create().WithStatusCode(200)
          .WithBodyAsJson(new { transactionId = "txn_123" }));

// Injecter l'URL dans la config de test
builder.UseSetting("PaymentService:BaseUrl", server.Url);

LocalStack (AWS S3, SQS) via Testcontainers

var localstack = new LocalStackBuilder().WithServices(Service.S3, Service.SQS).Build();
await localstack.StartAsync();

7. Contract testing avec Pact

// Consumer side (Jest + @pact-foundation/pact)
const provider = new PactV3({ consumer: "OrderService", provider: "PaymentService" });

it("expects a charge endpoint", async () => {
  await provider
    .addInteraction({ uponReceiving: "a charge request", ... })
    .executeTest(async (mockServer) => {
      const result = await chargeCard(mockServer.url, { amount: 100 });
      expect(result.transactionId).toBeDefined();
    });
});

Publier le contrat sur Pact Broker et déclencher la vérification côté fournisseur dans la CI.


8. Isolation et parallélisation


Garde-fous et anti-patterns

Anti-patternConséquenceCorrectif
Tests qui partagent l'état DB sans rollbackFlakiness, ordre-dépendanceRespawn ou transaction rollback
Mocker la couche repository dans un test d'intégrationOn ne teste plus l'intégrationUtiliser la vraie DB via Testcontainers
Thread.Sleep pour attendre un message brokerLenteur, flakinessWaitUntil / Polly avec timeout
Une seule WebApplicationFactory pour tous les testsConfig partagée, couplageFixture par suite ou WithWebHostBuilder par test
Ignorer les migrations : créer le schéma à la mainDésynchronisation avec prodToujours exécuter DbContext.Database.MigrateAsync() dans le fixture
Tests E2E en CI sur prodRisque de side effectsEnvironnement staging dédié, données synthétiques

Commandes utiles

# Lancer uniquement les tests d'intégration (xUnit + filtre par category)
dotnet test --filter "Category=Integration"

# Vitest avec tag
vitest run --reporter=verbose integration/

# Pytest avec marker
pytest -m integration -v

# Générer le rapport de couverture (coverage uniquement sur tests d'intégration)
dotnet test --filter "Category=Integration" --collect:"XPlat Code Coverage"

Bonnes pratiques 2026