Ihr kennt das: Die AI-Service Tests brauchen plötzlich 45 Sekunden statt 5. Die CI Pipeline bricht mit „Test timeout of 5000ms exceeded“ ab. Und dann diese endlosen }, 30000)
Callbacks in jedem einzelnen Test. Nach über 15 Jahren Erfahrung in der Softwarequalität haben wir bei Never Code Alone genau diese Timeout-Hölle unzählige Male gemeistert. Heute zeigen wir euch, wie ihr das Problem ein für alle Mal löst.
Die moderne JavaScript-Entwicklung mit Vite und Vitest bietet mächtige Möglichkeiten – wenn ihr wisst, wie ihr sie richtig konfiguriert. Lasst uns direkt in die häufigsten Fragen einsteigen, die uns in unseren Remote Consulting Sessions immer wieder begegnen.
FAQ 1: Wie setze ich globale Timeout-Werte für alle Tests?
Die Herausforderung: Jeder Test hat individuelle Timeout-Callbacks mit }, 30000)
am Ende. Das ist wartungstechnisch ein Albtraum und führt zu inkonsistenten Werten.
Die Lösung: Zentrale Konfiguration in der vite.config.ts
:
import { defineConfig } from 'vite';
export default defineConfig({
test: {
testTimeout: 25000, // 25 Sekunden für AI/API-Tests
hookTimeout: 10000, // 10 Sekunden für Setup/Teardown
}
});
Diese eine Zeile ersetzt hunderte individuelle Timeout-Definitionen. Bei der Eye-Able Datary konnten wir damit die Wartungszeit um 60% reduzieren und die Test-Stabilität von flackernden 70% auf solide 98% steigern.
FAQ 2: Wie konfiguriere ich unterschiedliche Timeouts für CI und lokale Entwicklung?
Die Herausforderung: CI-Server sind langsamer, lokale Entwicklung soll schnell bleiben.
Die Lösung: Dynamische Konfiguration basierend auf der Umgebung:
const getTestTimeout = () => {
if (process.env.CI === 'true') return 60000; // CI braucht mehr Zeit
if (process.env.TEST_MODE === 'integration') return 30000;
return 10000; // Standard Unit-Tests
};
export default defineConfig({
test: {
testTimeout: getTestTimeout(),
threads: process.env.CI === 'true' ? 1 : 4,
}
});
FAQ 3: Wie nutze ich Umgebungsvariablen in Vitest richtig?
Die Herausforderung: process.env.MEINE_VARIABLE
funktioniert nicht wie erwartet in Tests.
Die Lösung: Vitest lädt standardmäßig nur VITE_
prefixed Variablen. Für alle anderen:
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';
export default defineConfig(({ mode }) => ({
test: {
env: loadEnv(mode, process.cwd(), ''),
// Oder explizit eigene Variablen
env: {
NODE_ENV: 'test',
VITEST: 'true',
API_KEY: process.env.API_KEY
}
}
}));
FAQ 4: Wie vermeide ich Timeout-Probleme bei API-Tests?
Die Herausforderung: Externe API-Calls dauern unvorhersagbar lange (500ms bis 30+ Sekunden).
Die Lösung: Intelligentes Mocking statt echter API-Calls:
// Mock für deterministische Tests
vi.mock('../services/AI/OpenAIService.ts', () => ({
openAIService: {
generateResponse: vi.fn().mockResolvedValue({
text: 'Mocked response',
tokens: 42
})
}
}));
// Resultat: Von 20+ Sekunden auf konstante 8ms
Bei einem aktuellen Kundenprojekt reduzierten wir die Testlaufzeit von durchschnittlich 12 Minuten auf 45 Sekunden – bei gleichbleibender Testabdeckung.
FAQ 5: Was ist der Unterschied zwischen testTimeout und hookTimeout?
Die Herausforderung: Tests schlagen fehl, obwohl der testTimeout hoch genug ist.
Die Lösung: Separate Timeouts für verschiedene Phasen:
export default defineConfig({
test: {
testTimeout: 25000, // Für einzelne Tests
hookTimeout: 10000, // Für beforeEach, afterEach, etc.
teardownTimeout: 5000 // Für Cleanup-Operationen
}
});
FAQ 6: Wie konfiguriere ich Timeouts pro Test-Suite?
Die Herausforderung: Unit-Tests brauchen 500ms, Integration-Tests 30 Sekunden.
Die Lösung: Nutzt Test-Projekte mit eigenen Konfigurationen:
// vitest.config.ts
export default defineConfig({
projects: [
{
name: 'unit',
include: ['**/*.unit.test.ts'],
test: { testTimeout: 5000 }
},
{
name: 'integration',
include: ['**/*.integration.test.ts'],
test: { testTimeout: 30000 }
}
]
});
FAQ 7: Wie debugge ich Timeout-Probleme effektiv?
Die Herausforderung: „Test timeout exceeded“ – aber wo genau hängt es?
Die Lösung: Performance-Tracking einbauen:
// test-setup.ts
let testStartTime: number;
beforeEach(() => {
testStartTime = performance.now();
});
afterEach(() => {
const duration = performance.now() - testStartTime;
if (duration > 5000) {
console.warn(`⚠️ Slow test detected: ${duration}ms`);
}
});
FAQ 8: Wie setze ich Retry-Strategien für flaky Tests?
Die Herausforderung: Tests schlagen sporadisch wegen Netzwerk-Timeouts fehl.
Die Lösung: Automatische Wiederholungen konfigurieren:
export default defineConfig({
test: {
retry: process.env.CI === 'true' ? 2 : 0,
bail: 5, // Stop nach 5 Fehlern
testTimeout: 15000
}
});
FAQ 9: Wie optimiere ich Memory und Performance bei großen Test-Suites?
Die Herausforderung: Tests werden mit der Zeit immer langsamer.
Die Lösung: Ressourcen-Management aktivieren:
export default defineConfig({
test: {
pool: 'threads',
poolOptions: {
threads: {
singleThread: process.env.DEBUG === 'true',
minThreads: 1,
maxThreads: 4
}
},
// Memory-Limit für Worker
workerIdleMemoryLimit: '512MB'
}
});
FAQ 10: Wie integriere ich Coverage ohne Performance-Verlust?
Die Herausforderung: Coverage-Reports verdoppeln die Testlaufzeit.
Die Lösung: Intelligente Coverage-Konfiguration:
export default defineConfig({
test: {
coverage: {
provider: 'v8', // Schneller als istanbul
reporter: process.env.CI ? ['json'] : ['text'],
exclude: [
'node_modules/',
'**/*.test.ts',
'**/__mocks__/**'
],
// Coverage nur in CI erzwingen
enabled: process.env.CI === 'true'
}
}
});
Praxis-Beispiel: Von Chaos zu Stabilität
Ein konkretes Beispiel aus unserer Beratungspraxis: Ein SaaS-Startup kam zu uns mit einer Test-Suite, die regelmäßig nach 45 Minuten mit Timeouts abbrach. Das Problem:
- Über 200 individuelle Timeout-Definitionen
- Keine Unterscheidung zwischen Test-Typen
- Echte API-Calls in Unit-Tests
- Keine Parallelisierung
Unsere Lösung in 3 Schritten:
- Zentrale Konfiguration: Eine einzige
vite.config.ts
mit intelligenten Defaults - Test-Kategorisierung: Unit, Integration und E2E mit eigenen Timeout-Strategien
- Mock-First-Ansatz: Externe Dependencies nur in dedizierten Integration-Tests
Das Ergebnis:
- Testlaufzeit: Von 45 auf 3 Minuten
- Erfolgsrate: Von 60% auf 99.5%
- Wartungsaufwand: -80% durch zentrale Konfiguration
Best Practices aus über 15 Jahren Erfahrung
Nach unzähligen Projekten und Workshops haben wir folgende Kern-Prinzipien entwickelt:
1. Start Simple, Scale Smart
Beginnt mit einer Basis-Konfiguration und erweitert nur bei Bedarf.
2. Mock Early, Test Fast
Externe Dependencies gehören gemockt, außer ihr testet explizit die Integration.
3. Monitor Everything
Slow-Test-Detection sollte vom ersten Tag an aktiv sein.
4. Environment Matters
CI, Staging und lokale Entwicklung brauchen unterschiedliche Strategien.
Der Never Code Alone Weg
Bei Never Code Alone setzen wir auf nachhaltige Lösungen statt Quick-Fixes. Unsere Expertise in Softwarequalität und Remote Consulting hilft Teams, ihre Test-Infrastruktur grundlegend zu verbessern.
Ihr habt konkrete Herausforderungen mit eurer Test-Konfiguration? Ihr wollt eure CI/CD Pipeline endlich stabil bekommen? Meldet euch direkt bei uns: roland@nevercodealone.de
Wir bieten:
- Remote Code Reviews eurer Test-Konfiguration
- Hands-on Workshops mit der bewährten Funktastatur-Methode
- Langfristige Begleitung bei der Test-Automation
Fazit: Investiert in eure Test-Infrastruktur
Eine durchdachte Vite-Test-Konfiguration ist kein Nice-to-have, sondern die Basis für stabile Software. Die Zeit, die ihr heute in eine saubere Konfiguration investiert, spart ihr morgen hundertfach bei der Fehlersuche.
Die wichtigsten Takeaways:
- Zentrale Timeout-Konfiguration eliminiert Inkonsistenzen
- Umgebungsspezifische Settings machen Tests robust
- Intelligentes Mocking beschleunigt Test-Suites dramatisch
- Performance-Monitoring identifiziert Bottlenecks früh
Implementiert diese Strategien schrittweise. Startet mit zentralen Timeouts, fügt dann Mocking hinzu und optimiert kontinuierlich. Eure CI/CD Pipeline wird es euch danken – und euer Team auch.