Skip to content
Back to skills

Dev Integration Test Builder

ASecurity

Crée des tests d'intégration pour vérifier l'interaction entre composants. Se déclenche avec "test d'intégration", "integration test", "tester l'API", "tester la DB", "test end-to-end", "test E2E", "Testcontainers", "WebApplicationFactory". Also triggers on "integration tests", "test with a real database", "end-to-end API test".

  • 27 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 18, 2026
ai-agentspythongoc#bashsqlnodeexpressfastapiawstesting

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 18, 2026

npx -y skills add khalilbenaz/claude-skills-collection --skill dev-integration-test-builder --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev Integration Test Builder?

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

Security grade badge for Dev Integration Test Builder
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/khalilbenaz-dev-integration-test-builder/badge)](https://www.skillsdirectory.com/skills/khalilbenaz-dev-integration-test-builder)

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: dev-integration-test-builder
description: Crée des tests d'intégration pour vérifier l'interaction entre composants. Se déclenche avec "test d'intégration", "integration test", "tester l'API", "tester la DB", "test end-to-end", "test E2E", "Testcontainers", "WebApplicationFactory". Also triggers on "integration tests", "test with a real database", "end-to-end API test".
---

# Integration Test Builder

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

| Scénario | Choix recommandé |
|---|---|
| Controller + DB + auth sur vrai schéma | `WebApplicationFactory` + Testcontainers |
| Microservice consommant une API tierce | WireMock/MockServer + Testcontainers DB |
| Message broker (Kafka, RabbitMQ) | Testcontainers (image officielle) |
| Lambda/Cloud Function légère, pas de DB | Base in-memory + `TestClient` |
| Contrat entre deux microservices | Pact (CDC) |
| Smoke test post-déploiement | Test 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 :
- Endpoints REST/GraphQL exposés
- Accès DB (requêtes, transactions, contraintes FK, migrations)
- Broker de messages (topics/queues consommés ou produits)
- Services tiers appelés (paiement, email, stockage, SSO)

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)**
```csharp
// 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)**
```ts
// 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**
```csharp
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**
```csharp
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**
```python
# 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**
```ts
// 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

- Utiliser des **builders/factories** pour générer des entités cohérentes (pas de magic strings éparpillées).
- Seed minimal : créer uniquement les données nécessaires au test, pas un jeu de données global.
- Nettoyage : **rollback de transaction** (le plus propre) ou truncate après chaque test.

```csharp
// Builder pattern C#
var user = new UserBuilder().WithRole("admin").WithEmail("test@example.com").Build();
await dbContext.Users.AddAsync(user);
await dbContext.SaveChangesAsync();
```

```sql
-- 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**

```csharp
[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 :
- Cas nominal (200/201/204)
- Validation échouée (400 + message d'erreur structuré)
- Ressource absente (404)
- Conflit (409)
- Accès non autorisé (401/403)

---

### 6. Simuler les services externes

**WireMock.Net (.NET)**
```csharp
// 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**
```csharp
var localstack = new LocalStackBuilder().WithServices(Service.S3, Service.SQS).Build();
await localstack.StartAsync();
```

---

### 7. Contract testing avec Pact

```ts
// 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

- Chaque test doit pouvoir tourner **seul et dans n'importe quel ordre**.
- Ports dynamiques : Testcontainers gère cela automatiquement.
- Collections xUnit : `[Collection("db")]` pour partager un conteneur sans le redémarrer à chaque test — économise 5-15 s par suite.
- Ne jamais partager de données mutables entre tests sans transaction/rollback.

---

## Garde-fous et anti-patterns

| Anti-pattern | Conséquence | Correctif |
|---|---|---|
| Tests qui partagent l'état DB sans rollback | Flakiness, ordre-dépendance | Respawn ou transaction rollback |
| Mocker la couche repository dans un test d'intégration | On ne teste plus l'intégration | Utiliser la vraie DB via Testcontainers |
| `Thread.Sleep` pour attendre un message broker | Lenteur, flakiness | `WaitUntil` / `Polly` avec timeout |
| Une seule WebApplicationFactory pour tous les tests | Config partagée, couplage | Fixture par suite ou `WithWebHostBuilder` par test |
| Ignorer les migrations : créer le schéma à la main | Désynchronisation avec prod | Toujours exécuter `DbContext.Database.MigrateAsync()` dans le fixture |
| Tests E2E en CI sur prod | Risque de side effects | Environnement staging dédié, données synthétiques |

---

## Commandes utiles

```bash
# 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

- **Testcontainers Cloud** : décharger le démarrage des conteneurs sur un démon distant en CI pour réduire la durée des pipelines de 40-60 %.
- **Nommer les tests** comme des spécifications : `[Méthode]_[Contexte]_[Résultat attendu]` — lisible dans les rapports sans ouvrir le code.
- **Vérifier en DB** après un POST, pas seulement via la réponse HTTP — un bug de persistance silencieux passe sinon.
- **Séparer les collections CI** : `unit` (< 30 s), `integration` (< 3 min), `e2e` (optionnel sur merge seulement).
- **Ne pas tester la logique métier pure** dans un test d'intégration — c'est le rôle des tests unitaires. Un test d'intégration vérifie que les composants se parlent correctement.


## Communication Rules — MANDATORY

- Ultra-concise. No filler, no preamble, no pleasantries.
- Never say "happy to help", "sure!", "great question", "let me", or similar.
- Tool first, talk second. Act before explaining.
- Result first. Lead with outcome, not process.
- Stop when done. No summary, no recap, no trailing commentary.
- No politeness wrappers. Direct and blunt.
- Minimum words. If one word works, do not use ten.
- No unsolicited explanations.
- No emoji unless asked.

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.