CodeGym /Cours /ChatGPT Apps /Tests de GiftGenius — unit, contract, E2E et smoke dans l...

Tests de GiftGenius — unit, contract, E2E et smoke dans le CI

ChatGPT Apps
Niveau 17 , Leçon 2
Disponible

1. Que testons-nous réellement dans une ChatGPT App (et ce que nous ne testons pas)

Dans une application web classique, c’est clair : UI → backend → base de données. On écrit des tests unitaires pour les fonctions, des tests d’intégration pour les API, des E2E pour « l’utilisateur suit le parcours ».

Dans une ChatGPT App, le tableau est un peu plus complexe :

Utilisateur ↔ ChatGPT UI ↔ Widget (Apps SDK, React)
                  ↘
                    Serveur MCP (tools/resources)
                      ↘
                        ACP / backend / API externes

Le modèle à l’intérieur de ChatGPT décide quand appeler votre suggest_gifts, avec quels arguments, comment rendre le structuredContent issu de MCP et quand afficher votre widget.

Du point de vue des tests, il est pratique de séparer le monde en deux couches :

  • Tests d’infrastructure — c’est ce que nous faisons dans cette leçon. Nous vérifions que :
    • le code du widget ne casse pas lors d’un clic utilisateur ;
    • les outils MCP acceptent et renvoient des données au format promis par les schémas ;
    • les endpoints ACP et les webhooks sont vivants et ne tombent pas sur un JSON type.
  • Évaluations du comportement de l’IA — ce sera dans le module 20. Là, nous regardons ce que le modèle répond exactement : explique-t-il de manière adéquate, choisit-il correctement le cadeau au sens, ne « hallucine »-t-il pas.

Formule grossière du jour :

« Nous testons tout autour du LLM, mais pas le LLM lui-même ».

C’est précisément pourquoi le plan du cours souligne pour ce sujet : « Nous ne testons pas mot pour mot la réponse GPT, nous testons l’infrastructure autour et les contrats de données ».

Pour ne pas nous noyer, nous utilisons une simple « pyramide » de tests pour GiftGenius.

graph TD
  A["Tests unitaires
utils, logique métier des tools"] --> B[Tests de contrat
Zod/JSON Schema, webhooks] B --> C[E2E / tests UI
widget + MCP sans ChatGPT] C --> D["Smoke dans le CI
\"ça démarre au moins ?\""] style A fill:#e0f7fa,stroke:#00838f,stroke-width:1px style B fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px style C fill:#fff3e0,stroke:#ef6c00,stroke-width:1px style D fill:#ffebee,stroke:#c62828,stroke-width:1px

Nous allons passer chaque niveau et, en même temps, enrichir notre GiftGenius pédagogique avec des tests. Et pour finir, nous compilerons une check-list des erreurs typiques les plus fréquentes dans les tests d’une ChatGPT App.

2. Tests unitaires : découper GiftGenius en petits morceaux

Que considérer comme un « unit » dans une ChatGPT App

Dans notre stack, un test unitaire est la vérification d’une petite partie de logique isolée. Sans réseau réel, sans base de données et, si possible, sans appeler le framework MCP lui-même.

Dans GiftGenius, cela peut être :

  • une fonction de calcul de la « pertinence d’un cadeau » ;
  • un filtre qui supprime les articles sans prix ou avec une devise inadaptée ;
  • un convertisseur de devises ;
  • un mapper depuis l’objet « brut » d’un article vers GiftCardProps pour l’UI.

Idéalement, il faut aussi découper la logique des outils MCP : le handler de route MCP est une fine enveloppe qui appelle une fonction pure contenant la logique métier. Dans les tests unitaires, nous testons précisément la fonction pure.

Exemple : fonction de classement des cadeaux

Imaginons une utilitaire scoreGift qui, à partir d’une fourchette de prix et d’une popularité, attribue un « score » :

// src/lib/scoreGift.ts
export type Gift = {
  id: string;
  price: number;
  popularity: number; // 0..1
};

export function scoreGift(gift: Gift, maxPrice: number): number {
  if (gift.price > maxPrice) return 0;
  const priceScore = 1 - gift.price / maxPrice;
  return Math.round((priceScore * 0.6 + gift.popularity * 0.4) * 100);
}

Écrivons un test unitaire avec Jest (Vitest sera presque identique) :

// src/lib/scoreGift.test.ts
import { scoreGift } from './scoreGift';

test('scoreGift donne une note plus basse aux cadeaux chers', () => {
  const cheap = { id: 'c', price: 50, popularity: 0.5 };
  const expensive = { id: 'e', price: 100, popularity: 0.5 };

  const max = 100;
  const cheapScore = scoreGift(cheap, max);
  const expensiveScore = scoreGift(expensive, max);

  expect(cheapScore).toBeGreaterThan(expensiveScore);
});

On voit ici le « Arrange–Act–Assert » de base (on prépare les données, on appelle la fonction, on vérifie le résultat) — exactement l’approche structurelle à utiliser aussi dans des tests plus complexes.

Extraire la logique métier du handler MCP

Actuellement, vous avez probablement quelque chose comme :

// app/mcp/route.ts — fortement simplifié
import { createMcpServer } from '@modelcontextprotocol/sdk';
import { scoreGift } from '@/lib/scoreGift';

server.tool('suggest_gifts', {
  // ...
  handler: async ({ input }) => {
    const gifts = await fetchFromCatalog(input);
    const scored = gifts
      .map(g => ({ ...g, score: scoreGift(g, input.maxPrice) }))
      .sort((a, b) => b.score - a.score);

    return { gifts: scored.slice(0, 10) };
  },
});

Nous avons déjà écrit un test unitaire pour scoreGift, mais nous voulons aussi tester la fonction complète : « une fonction qui prend une liste de cadeaux et renvoie un top 10 trié ». Déplaçons-la dans un module séparé :

// src/lib/rankGifts.ts
import { scoreGift, Gift } from './scoreGift';

export function rankGifts(gifts: Gift[], maxPrice: number) {
  return gifts
    .map(g => ({ ...g, score: scoreGift(g, maxPrice) }))
    .sort((a, b) => b.score - a.score)
    .slice(0, 10);
}

Et le test :

// src/lib/rankGifts.test.ts
import { rankGifts } from './rankGifts';

test('rankGifts renvoie au maximum 10 cadeaux par score décroissant', () => {
  const gifts = Array.from({ length: 20 }, (_, i) => ({
    id: `g${i}`,
    price: 10 + i,
    popularity: 0.5,
  }));

  const result = rankGifts(gifts, 100);

  expect(result).toHaveLength(10);
  expect(result[0].score).toBeGreaterThanOrEqual(result[9].score);
});

Ces tests unitaires sont rapides, peu coûteux et donnent un feedback immédiat — c’est précisément pourquoi on les recommande comme la « base large de la pyramide de tests » pour les services MCP.

Tests unitaires pour les outils MCP : mocker les API externes

Erreur fréquente : tenter de « tester unitairement » le handler d’un outil MCP avec de vraies requêtes HTTP vers un catalogue, Stripe, etc. Au final, le test devient lent et fragile.

La meilleure option : ne laisser dans le handler que l’assemblage (wiring) et extraire toute la logique complexe dans des fonctions que nous testons déjà séparément. Si vous souhaitez vraiment tester le handler lui-même, remplacez les dépendances par des mocks. C’est exactement ce que recommandent les revues détaillées sur les tests MCP : mocker les API externes dans les tool-handlers.

3. Tests de contrat : Zod/JSON Schema comme « contrat » avec le modèle et l’ACP

Qu’est-ce qu’un test de contrat dans notre contexte

La logique unitaire est sous contrôle : les petites fonctions pures sont couvertes. La couche suivante de la pyramide consiste à s’assurer que les services se comprennent toujours via les contrats JSON. Ce sont précisément les tests de contrat.

Le test de contrat vérifie que deux parties qui échangent des données se comprennent toujours. Le focus n’est pas sur les algorithmes internes, mais sur la forme et le sens du JSON : champs, types, caractère obligatoire.

Dans une ChatGPT App, nous avons beaucoup de tels contrats :

  • ChatGPT ↔ MCP : inputSchema et outputSchema des outils MCP.
  • MCP ↔ commerce‑API (ACP) : format des requêtes create_checkout_session, structure des réponses.
  • ACP ↔ notre backend via webhooks : order.created, payment_failed, etc.

Si vous modifiez un schéma mais oubliez de mettre à jour le code (ou inversement — vous changez le code mais laissez l’ancien schéma), une rupture silencieuse apparaît. Le modèle continue d’envoyer l’ancien JSON, tandis que votre code attend déjà un nouveau champ — et il tombe à l’exécution. Ce sont précisément ces situations que les tests de contrat doivent détecter avant la production.

Zod comme source de vérité unique

Dans l’écosystème JavaScript/TypeScript, Zod convient très bien à cela, et vous l’avez déjà utilisé avec MCP : le SDK sait convertir les schémas Zod en JSON Schema pour déclarer des outils.

Par exemple, décrivons le schéma d’un cadeau et le résultat d’une recommandation :

// src/schemas/gift.ts
import { z } from 'zod';

export const GiftSchema = z.object({
  id: z.string(),
  title: z.string(),
  price: z.number().nonnegative(),
  currency: z.string().length(3),
  url: z.string().url(),
});

export const SuggestGiftsResultSchema = z.object({
  gifts: z.array(GiftSchema).min(1),
});

On obtient les types pour le code via z.infer :

export type Gift = z.infer<typeof GiftSchema>;
export type SuggestGiftsResult = z.infer<typeof SuggestGiftsResultSchema>;

C’est déjà une sorte de contract test au compile-time : si vous essayez quelque part dans le code d’assigner currency: 123, TypeScript vous rappellera que cela doit être une string.

Tests de contrat au runtime pour les schémas

Encore mieux : des tests au runtime qui passent des exemples de données réelles (ou proches du réel) à travers les schémas.

// src/schemas/gift.test.ts
import { GiftSchema, SuggestGiftsResultSchema } from './gift';

test('GiftSchema accepte un article valide', () => {
  const sample = {
    id: '123',
    title: 'Tasse avec un chat',
    price: 19.99,
    currency: 'USD',
    url: 'https://example.com/gift/123',
  };

  expect(() => GiftSchema.parse(sample)).not.toThrow();
});

test('SuggestGiftsResultSchema rejette une liste de cadeaux vide', () => {
  const badResult = { gifts: [] };

  expect(() => SuggestGiftsResultSchema.parse(badResult)).toThrow();
});

Pourquoi c’est important :

  • si vous montrez dans les prompts/la documentation des exemples de JSON pour le modèle, vous pouvez les placer directement dans ces tests et garantir que « l’exemple ne ment pas » ;
  • si vous modifiez le schéma (par exemple, rendre le champ url obligatoire), les tests mettront immédiatement en évidence tous les anciens exemples et fixtures qui ne sont plus valides.

Les recommandations officielles de l’Apps SDK soulignent : le structured content doit correspondre au outputSchema déclaré, sinon le modèle peut ne pas le comprendre. Les tests sur les schémas sont la première ligne de défense pour éviter les divergences.

Contrats des webhooks et de l’ACP

Le même principe s’applique aux webhooks et aux endpoints ACP. Supposons que nous ayons OrderCreated :

// src/schemas/acp.ts
import { z } from 'zod';

export const OrderCreatedSchema = z.object({
  id: z.string(),
  userId: z.string(),
  totalAmount: z.number(),
  currency: z.string().length(3),
  status: z.literal('created'),
});

Test :

// src/schemas/acp.test.ts
import { OrderCreatedSchema } from './acp';

test("OrderCreatedSchema valide l'exemple de webhook", () => {
  const sample = {
    id: 'ord_1',
    userId: 'user_42',
    totalAmount: 59.99,
    currency: 'USD',
    status: 'created',
  };

  expect(() => OrderCreatedSchema.parse(sample)).not.toThrow();
});

Ensuite, dans le handler du webhook, vous faites d’abord OrderCreatedSchema.parse(body) — et vous êtes assuré de travailler avec un objet valide.

OpenAI, dans sa check-list de régression pour les Apps, recommande également de maintenir les schémas à jour au fur et à mesure de l’évolution de l’application — les tests de contrat garantissent justement que vous ne l’oublierez pas.

4. Tester le widget et « presque E2E » : comment se passer de chatgpt.com

Les tests unitaires maintiennent la logique en ordre, les tests de contrat — la forme des données entre services. Mais la pyramide ne s’arrête pas là : nous devons aussi vérifier que tout le parcours utilisateur à travers le widget et MCP fonctionne réellement comme un tout. Pour une ChatGPT App, ce sera un format particulier, « presque E2E ».

Pourquoi on ne peut pas simplement « lancer Playwright » sur ChatGPT

Réflexe intuitif : « Ouvrons https://chatgpt.com, lançons le widget, parcourons tout le scénario “choisir un cadeau → passer la commande” avec Playwright, et nous aurons un vrai E2E ».

Hélas, non.

Problèmes :

  • un passage automatisé sur chatgpt.com enfreint les ToS ;
  • il existe une protection (Cloudflare, 2FA, etc.) qui n’aime pas du tout les bots venant du CI ;
  • le comportement du modèle est variable : aujourd’hui, il a appelé votre suggest_gifts, demain il décide de se contenter d’une réponse textuelle.

Par conséquent, pour une ChatGPT App, le test E2E est interprété plus largement : nous testons le parcours complet au sein de notre application — widget + MCP + ACP — mais sans l’UI ChatGPT réel et sans le modèle réel.

Les guides détaillés proposent justement la stratégie suivante : tester séparément le serveur MCP avec un client headless, et le widget dans un « hôte de test » avec un window.openai mocké.

Tester le widget en tant que composant React

Option de base : React Testing Library. Il nous faut :

  1. Monter le composant GiftGeniusWidget.
  2. Lui injecter un faux window.openai avec les méthodes nécessaires (callTool, openExternal, etc.).
  3. Se faire passer pour un utilisateur : cliquer des boutons, saisir du texte.
  4. Vérifier que callTool est appelé avec les bons arguments et que l’UI affiche le résultat attendu.

Supposons que nous ayons un widget simplifié :

// src/app/GiftGeniusWidget.tsx
'use client';
import React from 'react';

export function GiftGeniusWidget() {
  const [loading, setLoading] = React.useState(false);

  async function handleClick() {
    setLoading(true);
    await (window as any).openai.callTool('suggest_gifts', {
      occasion: 'birthday',
    });
    setLoading(false);
  }

  return (
    <div>
      <button onClick={handleClick}>Trouver un cadeau</button>
      {loading && <p>Un instant, je cherche des idées…</p>}
    </div>
  );
}

Test :

// src/app/GiftGeniusWidget.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { GiftGeniusWidget } from './GiftGeniusWidget';

test("le bouton appelle suggest_gifts via window.openai.callTool", async () => {
  const callToolMock = vi.fn().mockResolvedValue({});
  (window as any).openai = { callTool: callToolMock };

  render(<GiftGeniusWidget />);

  const button = screen.getByText('Trouver un cadeau');
  await fireEvent.click(button);

  expect(callToolMock).toHaveBeenCalledWith('suggest_gifts', {
    occasion: 'birthday',
  });
});

Ici, nous contrôlons totalement l’environnement :

  • aucun véritable ChatGPT ;
  • aucun réseau ;
  • un test simple et rapide qui vérifie le lien « UI → window.openai ».

C’est ce que recommande la documentation de l’Apps SDK : mocker window.openai lors des tests du widget pour ne pas dépendre de l’environnement réel.

E2E‑light avec Playwright : Next.js + MCP

Niveau suivant : nous lançons localement l’application Next.js (comme en Dev Mode), mais nous y accédons non pas via ChatGPT, mais directement depuis le navigateur du test.

Scénario pertinent à vérifier :

  1. Ouvrir la page /widget (ou / — selon votre projet).
  2. Imiter un minimum d’étapes : choisir un type de cadeau, cliquer sur « Afficher des idées ».
  3. Vérifier que le widget affiche des cartes cadeau.
  4. (Optionnel) cliquer une carte, appuyer sur « Passer au paiement » et s’assurer que le mock ACP renvoie un succès.

Mini‑exemple de test Playwright :

// tests/e2e/gift-flow.spec.ts
import { test, expect } from '@playwright/test';

test("l'utilisateur peut choisir un cadeau et voir les résultats", async ({ page }) => {
  await page.goto('http://localhost:3000/widget');

  await page.click('text=Cadeau d\'anniversaire');
  await page.click('text=Trouver');

  await page.waitForSelector('[data-testid="gift-card"]');

  const cards = await page.locator('[data-testid="gift-card"]').all();
  expect(cards.length).toBeGreaterThan(0);
});

Sur un projet réel, on y ajoutera :

  • le démarrage de npm run dev ou d’un test-server dédié dans le beforeAll de Playwright ;
  • des mocks pour MCP/ACP afin de ne pas toucher les services de production.

Mais même un scénario aussi simple attrape déjà les « cassures » typiques entre le widget et MCP : URL incorrecte, erreurs CORS, structuredContent incorrect, etc.

5. Tests smoke dans le CI : vérifier que « ça démarre au moins »

Il reste la couche supérieure, la plus légère, de notre pyramide — les tests smoke. Ils ne vérifient pas tout le parcours comme l’E2E‑light, mais donnent simplement une réponse : l’application est-elle vivante et démarre-t-elle avant le déploiement ?

Smoke vs E2E complet

Vous avez déjà entendu parler d’un smoke test « manuel » dans le deuxième module : nous avions lancé le tout premier « Hello GiftGenius », vérifié que le widget se rendait, que ChatGPT le voyait et que le bouton ouvrait un lien. L’objectif était de s’assurer que Dev Mode + tunnel + configuration Apps SDK étaient corrects.

Maintenant, la tâche est similaire, seulement automatisée et dans le CI :

  • nous n’essayons pas de modéliser tous les scénarios utilisateur ;
  • nous ne parlons pas au ChatGPT réel ;
  • nous vérifions seulement que :
    • l’app Next.js démarre ;
    • le serveur MCP répond au moins à tools/list / tools/call ;
    • l’endpoint ACP est vivant et renvoie 200 sur un JSON de test.

C’est particulièrement important avant un déploiement en production ou avant l’envoi d’une nouvelle version au Store : il est plus simple d’attraper « tout a planté et ne démarre pas » dans le CI que de l’apprendre des utilisateurs.

Exemple de test smoke pour les outils MCP

Supposons que nous ayons un module utilitaire qui démarre un serveur MCP dans le test ou utilise un client MCP du SDK. Conceptuellement, le test ressemble à ceci :

// tests/smoke/mcp-tools.smoke.test.ts
import { createTestMcpClient } from './testClient';

test("MCP répond à tools.list et tools.call(suggest_gifts)", async () => {
  const client = await createTestMcpClient(); // démarre le serveur ou s'y connecte

  const tools = await client.listTools();
  expect(tools.some(t => t.name === 'suggest_gifts')).toBe(true);

  const result = await client.callTool('suggest_gifts', {
    occasion: 'birthday',
    budget: { currency: 'USD', max: 50 },
  });

  expect(result.gifts.length).toBeGreaterThan(0);
});

Dans les analyses plus poussées des tests MCP, on conseille justement cette approche : utiliser un client MCP dans les tests pour vérifier le cycle complet JSON‑RPC — list → call → réponse.

L’implémentation de createTestMcpClient peut être cachée dans des utilitaires : elle démarre le serveur dans le même processus ou se connecte à une instance déjà lancée.

Test smoke pour ACP/checkout

De même, on peut écrire un test très simple pour la couche commerce, sans simuler un paiement réel :

// tests/smoke/acp.smoke.test.ts
import fetch from 'node-fetch';

test('ACP test-intent renvoie 200', async () => {
  const res = await fetch('http://localhost:3000/api/acp/test-intent', {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({
      amount: 10,
      currency: 'USD',
    }),
  });

  expect(res.ok).toBe(true);
});

Ici, peu importe ce que fait test-intent — il peut simplement vérifier l’accès à la base et renvoyer {"status":"ok"}. L’essentiel est que le CI attrape :

  • une variable d’environnement oubliée ;
  • une route cassée ;
  • un parsing JSON défectueux.

Pipeline CI minimal

Les détails du CI/CD viendront dans les modules sur le déploiement, mais un pipeline de base peut ressembler à ceci (exemple GitHub Actions) :

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ main ]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - run: npm test           # unit + contract
      - run: npm run test:e2e   # e2e/ui
      - run: npm run test:smoke # smoke mcp/acp

Les commandes npm run test:e2e et npm run test:smoke peuvent déjà démarrer le serveur de dev, attendre sa disponibilité et lancer Playwright / des scripts Node.

6. Mini‑carte des tests pour GiftGenius

Pour ne pas se perdre, rassemblons tout dans un tableau — ce que nous testons à chaque niveau et aux questions auxquelles cela répond.

Niveau Exemples pour GiftGenius Outils À quelle question cela répond
Unit scoreGift, rankGifts, validateurs de budget Jest / Vitest La logique calcule-t-elle correctement ?
Contract (schemas) Schémas Zod Gift, SuggestGiftsResult, OrderCreated Zod, AJV Parlons-nous toujours le même langage JSON avec GPT/ACP ?
UI/Component Comportement du widget au clic, appel de window.openai.callTool React Testing Library L’UI déclenche-t-elle les bonnes actions ?
E2E‑light L’utilisateur suit le parcours de choix d’un cadeau et voit les cartes Playwright/Cypress Toutes les parties de GiftGenius s’assemblent-elles en un flux fonctionnel ?
Smoke dans le CI MCP répond à tools.list/call, ACP test-intent 200 Scripts Node, client MCP L’application est-elle vivante et connectée ?

Cet ensemble est le « minimum viable » de tests pour une ChatGPT App, tel que décrit dans le plan du module : sans une équipe QA d’entreprise, mais avec la garantie de base que la production ne tombe pas au moindre souci.

7. Erreurs typiques lors des tests d’une ChatGPT App

Erreur n° 1 : vouloir tester de manière déterministe les réponses du modèle.
Parfois, des développeurs écrivent des tests du style « j’attends que GPT réponde par la chaîne Voici 5 idées de cadeaux ». Ces tests sont fragiles par définition : le modèle n’a aucune obligation de répéter une formulation mot pour mot, et le modèle lui-même peut évoluer. Dans ce module, nous ne touchons pas au contenu des réponses — nous vérifions seulement que les outils sont appelés, les schémas valides, le flux ne tombe pas. L’évaluation de la qualité des textes est une discipline séparée (M20, LLM‑evals).

Erreur n° 2 : absence de tests de contrat pour les schémas MCP.
Il est très tentant de décrire un schéma Zod une fois et de l’oublier. Puis vous ajoutez dans le résultat de l’outil un champ discount, vous mettez à jour le code, mais pas le schéma. Le modèle continue d’envoyer l’ancien format, et votre code attend le nouveau champ — en production, des plantages étranges commencent. Les tests de contrat via Zod/JSON Schema empêchent précisément ces « casses silencieuses », donc les négliger est une erreur courante et très douloureuse.

Erreur n° 3 : tenter de lancer un E2E sur chatgpt.com depuis le CI.
Certains essaient quand même : ils lancent Playwright contre le ChatGPT réel, se connectent, cliquent dans l’UI — et récoltent un ban de Cloudflare, des tests instables et une violation potentielle des conditions d’utilisation. La bonne voie — tester votre hôte Next.js + MCP isolément, en mockant window.openai et les API externes, comme le recommandent les guides Apps SDK et MCP.

Erreur n° 4 : n’écrire que de l’E2E et oublier le niveau unitaire.
On voit parfois un projet avec un « énorme » test E2E qui clique à travers la moitié de l’application, et zéro test unitaire. Cette approche donne une fausse impression de protection : le test est soit vert, soit rouge, mais il est presque impossible de localiser la cause, et chaque exécution prend des minutes. Il est bien plus efficace d’avoir des dizaines de tests unitaires rapides pour les fonctions pures et deux ou trois scénarios E2E‑light propres sur les parcours critiques.

Erreur n° 5 : utiliser de vraies API externes dans les tests ordinaires.
Stripe, des catalogues externes, des CRM — parfaits pour des tests d’intégration dans un environnement contrôlé, mais pas pour un banal npm test. Si vos tests dépendent du réseau, des rate limits des tiers et d’un serveur de prod tiers, ils échoueront pour des raisons sans lien avec votre code. La meilleure approche — mocker l’API externe (via nock, msw, etc.) et avoir à part quelques vérifications « live » dans un environnement spécial.

Erreur n° 6 : oublier les tests smoke avant le déploiement.
On assemble une fonctionnalité, on met à jour le schéma MCP, on ajuste l’UI, on clique « Deploy » — et Next.js ne démarre pas, parce que quelqu’un a cassé le next.config ou supprimé le .env. Sans tests smoke automatisés, le CI laisse passer de tels échecs évidents en production. Une simple suite smoke qui vérifie « le serveur démarre », « MCP répond à un appel de base » et « l’endpoint ACP de test renvoie 200 » économise des heures de debug et bien des nerfs.

Erreur n° 7 : complexifier à l’excès l’environnement de test au début.
Parfois, inspirés par les best practices de grandes entreprises, on veut tout de suite mettre en place une dizaine d’environnements, des tests de contrat complexes avec génération de données, des scénarios de charge, etc. La conséquence : l’équipe passe des semaines sur l’infrastructure et cesse de livrer des fonctionnalités. Pour démarrer avec une ChatGPT App, le « Sanity Suite » dont nous avons parlé suffit : unit + contract + quelques E2E‑light + smoke dans le CI. Ensuite, on pourra faire évoluer au fur et à mesure de la croissance du trafic et des exigences.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION