Tester et débugger
Tester votre app avant la publication
Une application bien testée est une application qui passe la review du Store et qui satisfait ses utilisateurs. Le Apps SDK fournit des outils de test et de débogage intégrés que vous devez maîtriser.
Le Playground de développement
Le playground est votre premier outil de test. Il simule l’environnement ChatGPT en local.
# Lancer le playground
npx chatgpt-app dev
# Options disponibles
npx chatgpt-app dev --port 3200 # Port personnalisé
npx chatgpt-app dev --verbose # Logs détaillés
npx chatgpt-app dev --mock-auth # Simuler l'authentification
Le playground affiche :
- Une interface de conversation simulée
- Un panneau de logs en temps réel
- Un inspecteur de widgets
- Un moniteur de requêtes réseau
Tests unitaires des actions
Testez vos actions indépendamment avec le test runner du SDK :
// tests/actions/weather.test.ts
import { testAction } from "@openai/apps-sdk/testing";
import { getWeather } from "../src/actions/weather";
describe("getWeather", () => {
it("retourne la météo pour une ville valide", async () => {
const result = await testAction(getWeather, {
params: { city: "Paris" },
mockContext: { user: { id: "test-user" } },
});
expect(result.city).toBe("Paris");
expect(result.temperature).toBeDefined();
expect(typeof result.temperature).toBe("number");
});
it("gère les villes inconnues", async () => {
await expect(
testAction(getWeather, {
params: { city: "VilleInexistante123" },
})
).rejects.toThrow("NOT_FOUND");
});
it("respecte le rate limiting", async () => {
// Appeler 21 fois (limite = 20/min)
for (let i = 0; i < 20; i++) {
await testAction(getWeather, { params: { city: "Lyon" } });
}
await expect(
testAction(getWeather, { params: { city: "Lyon" } })
).rejects.toThrow("RATE_LIMITED");
});
});
Tests de widgets
Vérifiez que vos widgets produisent le rendu attendu :
// tests/widgets/weather-card.test.ts
import { testWidget } from "@openai/apps-sdk/testing";
import { weatherCard } from "../src/widgets/weather-card";
describe("weatherCard", () => {
it("affiche correctement les données météo", () => {
const rendered = testWidget(weatherCard, {
city: "Paris",
temperature: 22,
windSpeed: 15,
condition: "Ciel dégagé",
timestamp: "2026-04-01T10:00:00Z",
});
expect(rendered.type).toBe("card");
expect(rendered.title).toContain("Paris");
// Vérifier les métriques
const metrics = rendered.content.find((c) => c.type === "grid");
expect(metrics.items).toHaveLength(2);
expect(metrics.items[0].value).toBe("22°C");
});
it("gère les données manquantes", () => {
const rendered = testWidget(weatherCard, {
city: "Lyon",
temperature: null,
});
// Le widget ne doit pas crasher
expect(rendered.type).toBe("card");
});
});
Tests d’intégration (flows)
Testez le parcours complet action → widget :
// tests/flows/weather-flow.test.ts
import { testFlow } from "@openai/apps-sdk/testing";
import { app } from "../src/index";
describe("Weather Flow", () => {
it("affiche la météo après recherche", async () => {
const result = await testFlow(app, {
userMessage: "Quelle est la météo à Marseille ?",
expectedAction: "getWeather",
expectedWidget: "weatherCard",
});
expect(result.actionCalled).toBe(true);
expect(result.widgetRendered).toBe(true);
expect(result.widgetData.city).toBe("Marseille");
});
});
Débogage en temps réel
Logs structurés
Le SDK fournit un logger intégré :
import { logger } from "@openai/apps-sdk";
handler: async ({ city }, context) => {
logger.info("Recherche météo", { city, userId: context.user.id });
try {
const data = await fetchWeather(city);
logger.debug("Données reçues", { temperature: data.temp });
return data;
} catch (error) {
logger.error("Erreur API météo", { city, error: error.message });
throw new ActionError("INTERNAL", "Service météo indisponible");
}
}
Inspecteur de requêtes
Le playground inclut un inspecteur réseau qui affiche :
- Chaque requête HTTP sortante (URL, headers, body)
- Le temps de réponse
- Le code de statut
- Le body de la réponse
Mode debug avancé
# Activer les logs détaillés
CHATGPT_APP_DEBUG=true npx chatgpt-app dev
# Logs de chaque décision du modèle
CHATGPT_APP_DEBUG=model npx chatgpt-app dev
# Logs des échanges réseau
CHATGPT_APP_DEBUG=network npx chatgpt-app dev
Erreurs courantes et solutions
| Erreur | Cause probable | Solution |
|---|---|---|
| ACTION_NOT_FOUND | Action non enregistrée | Vérifier app.action() dans index.ts |
| WIDGET_RENDER_ERROR | Données invalides pour le widget | Valider les données avant le render |
| AUTH_TOKEN_EXPIRED | Token OAuth expiré | Implémenter le refresh token |
| TIMEOUT | Action trop lente (> 30s) | Optimiser ou découper l'action |
Checklist avant soumission
Avant de soumettre votre app au Store, vérifiez :
- Toutes les actions retournent des données valides pour le cas nominal
- Les erreurs sont gérées avec des
ActionErrorexplicites - Les widgets ne crashent pas avec des données partielles ou nulles
- L’authentification fonctionne de bout en bout
- Le rate limiting est configuré sur les actions sensibles
- Les tests passent à 100 %
Points clés à retenir
- Le playground simule ChatGPT en local pour tester sans publier
- Testez actions, widgets et flows séparément avec les helpers du SDK
- Utilisez le logger structuré pour un débogage efficace
- Les erreurs courantes ont des solutions connues — consultez la table de référence
- Passez la checklist de pré-soumission avant de publier sur le Store