Cazuri de testare generate de AI: Utilizarea LLM ca redactor automat de teste
Scrierea testelor este plictisitoare, consumatoare de timp și amână. De câte ori ai văzut un PR fără un singur test nou de ce l-am „adăugat la restanță”? LLM-urile schimbă acest lucru scenariu: GitHub Copilot, Claude și GPT-4 pot genera cazuri de testare de o calitate surprinzătoare pornind de la codul sursă, poveștile utilizatorilor sau specificațiile API - reducând timpul de scriere teste cu 40-60% și scăderea barierei psihologice care duce la omiterea acestora.
Dar nu este suficient să ceri AI să „scrie testele” și să le folosească orbește. Acest ghid arată un flux de lucru structurat pentru a genera teste de înaltă calitate, a le valida și a le integra în pipeline CI.
Ce vei învăța
- Strategii de încurajare pentru a genera cazuri de testare eficiente
- Flux de lucru GitHub Copilot pentru testarea unitară din codul sursă
- Generarea de teste din poveștile utilizatorilor și specificațiile BDD
- Cum se validează calitatea testelor generate de AI
- Integrare cu testarea mutațiilor pentru a verifica valoarea reală
- Limite și riscuri: când testele AI nu sunt suficiente
Problema cu testele scrise de AI fără verificare
Înainte de a intra în fluxul de lucru, un avertisment critic: LLM-urile generează teste care trec
testează cu ușurință, dar nu neapărat, comportamentul corect. Cel mai comun model este
„test fantomă” — un test care verifică asta result !== null în loc să verifice
valoarea reală.
// ESEMPIO DI TEST AI GENERATO SCARSO (da evitare)
// Copilot ha generato questo — sembra un test, ma non verifica nulla di utile
import { calculateDiscount } from './pricing';
describe('calculateDiscount', () => {
it('should return a value', () => {
const result = calculateDiscount(100, 'PROMO10');
expect(result).toBeDefined(); // INUTILE: non verifica il valore corretto
expect(result).not.toBeNull(); // INUTILE: solo dice "non e null"
expect(typeof result).toBe('number'); // DEBOLE: non verifica che sia 90
});
});
// ESEMPIO DI TEST AI GENERATO BUONO (con prompt corretto)
describe('calculateDiscount', () => {
it('applica sconto PROMO10 del 10% sul prezzo base', () => {
expect(calculateDiscount(100, 'PROMO10')).toBe(90);
});
it('restituisce il prezzo originale per codice non valido', () => {
expect(calculateDiscount(100, 'INVALID')).toBe(100);
});
it('applica sconto massimo del 50% anche per codici piu generosi', () => {
expect(calculateDiscount(100, 'SUPER80')).toBe(50); // cap al 50%
});
it('gestisce prezzi a zero senza errori', () => {
expect(calculateDiscount(0, 'PROMO10')).toBe(0);
});
it('lancia errore per prezzi negativi', () => {
expect(() => calculateDiscount(-10, 'PROMO10')).toThrow(RangeError);
});
});
Solicitare eficientă pentru GitHub Copilot
Calitatea testelor generate depinde direct de calitatea promptului. Iată strategiile mai eficient:
// STRATEGIA 1: Commento contestuale nel file di test
// Il commento guida Copilot nel generare test completi
// src/utils/string-validator.ts
export function validateEmail(email: string): boolean {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
export function validatePassword(password: string): {
valid: boolean;
errors: string[];
} {
const errors: string[] = [];
if (password.length < 8) errors.push('Minimo 8 caratteri');
if (!/[A-Z]/.test(password)) errors.push('Almeno una maiuscola');
if (!/[0-9]/.test(password)) errors.push('Almeno un numero');
if (!/[!@#$%]/.test(password)) errors.push('Almeno un carattere speciale');
return { valid: errors.length === 0, errors };
}
// src/utils/string-validator.test.ts
// Test per validateEmail e validatePassword.
// Coprire: email valide, email non valide (mancano @, dominio, TLD),
// password valida, password troppo corta, password senza maiuscola,
// senza numero, senza speciale, stringa vuota, valori limite.
// Usare describe nested per raggruppare casi validi e invalidi.
// I test devono essere deterministici, no mocks necessari.
import { validateEmail, validatePassword } from './string-validator';
describe('validateEmail', () => {
describe('email valide', () => {
test.each([
['user@example.com'],
['user.name+tag@company.co.uk'],
['123@numbers.org'],
])('%s deve essere valida', (email) => {
expect(validateEmail(email)).toBe(true);
});
});
describe('email non valide', () => {
test.each([
['not-an-email'],
['missing@'],
['@nodomain.com'],
['spaces in@email.com'],
[''],
])('%s deve essere non valida', (email) => {
expect(validateEmail(email)).toBe(false);
});
});
});
describe('validatePassword', () => {
it('password valida supera tutti i controlli', () => {
const result = validatePassword('SecureP@ss1');
expect(result.valid).toBe(true);
expect(result.errors).toHaveLength(0);
});
it('password troppo corta produce errore specifico', () => {
const result = validatePassword('Ab1@');
expect(result.valid).toBe(false);
expect(result.errors).toContain('Minimo 8 caratteri');
});
});
Generare din poveștile utilizatorilor cu Claude
Claude este deosebit de eficient în transformarea poveștilor utilizatorilor în cazuri de testare structurate, inclusiv cazuri de margine pe care dezvoltatorii tind să le uite.
"""
Prompt per Claude: Generazione test da User Story
"""
user_story = """
User Story: Come utente registrato, voglio aggiungere prodotti al carrello
in modo da poter procedere all'acquisto.
Criteri di accettazione:
- L'utente puo aggiungere un prodotto disponibile al carrello
- Il contatore nel header si aggiorna immediatamente
- Non si possono aggiungere prodotti esauriti
- La quantita massima per prodotto e 10
- Un prodotto gia nel carrello aumenta la quantita (non crea duplicato)
- I prodotti nel carrello persistono dopo refresh della pagina
"""
prompt = f"""Sei un QA engineer esperto in BDD e test automation.
Data la seguente user story e criteri di accettazione, genera:
1. Casi di test Playwright in TypeScript per i test E2E
2. Unit test per la funzione addToCart(productId, quantity) in Vitest
3. Test cases in formato Gherkin (BDD) per la documentazione
Per ogni test specifica:
- Scenario (nome descrittivo)
- Precondizioni
- Azioni
- Risultato atteso
Includi casi happy path, edge cases e casi di errore.
User Story:
{user_story}
Genera i test nel formato richiesto, con commenti che spiegano il
rationale di ogni caso di test."""
# Risposta Claude genera 15-20 test cases strutturati con Playwright + Vitest + Gherkin
# Esempio output Claude in Gherkin
Feature: Aggiunta prodotti al carrello
Background:
Given l'utente e autenticato
And il catalogo prodotti e disponibile
Scenario: Aggiunta prodotto disponibile
When l'utente clicca "Aggiungi al carrello" sul prodotto "Laptop Pro X"
Then il carrello contiene 1 unita di "Laptop Pro X"
And il contatore nell'header mostra "1"
Scenario: Prodotto gia nel carrello
Given il carrello contiene 1 unita di "Laptop Pro X"
When l'utente clicca "Aggiungi al carrello" sullo stesso prodotto
Then il carrello contiene 2 unita di "Laptop Pro X"
And non viene creato un record duplicato
Scenario: Tentativo aggiunta prodotto esaurito
Given il prodotto "Tablet Z" ha disponibilita 0
Then il bottone "Aggiungi al carrello" per "Tablet Z" e disabilitato
Scenario: Limite quantita massima
Given il carrello contiene 10 unita di "Mouse Wireless"
When l'utente tenta di aggiungere un'altra unita
Then viene mostrato il messaggio "Quantita massima raggiunta (10)"
And la quantita rimane 10
Flux de lucru complet: de la cod la teste validate
// Workflow in 5 step per test AI-generated di qualita
// STEP 1: Genera i test
// Prompt: "Genera test completi per questo servizio con casi happy path,
// edge cases, casi di errore. Usa Vitest e TypeScript."
// [AI genera tests/payment.service.test.ts]
// STEP 2: Esegui i test generati
// npm run test -- tests/payment.service.test.ts
// ATTESO: tutti passano (se l'implementazione e corretta)
// STEP 3: Verifica mutation score
// npx stryker run -- solo sui file modificati
// TARGET: mutation score > 60% sui test AI-generated
// STEP 4: Review manuale
const REVIEW_CHECKLIST = `
[ ] I test coprono i criteri di accettazione?
[ ] I test verificano il comportamento (non l'implementazione)?
[ ] Ci sono edge cases mancanti? (null, undefined, stringhe vuote, valori limite)
[ ] I test sono deterministici? (no Date.now(), no Math.random() senza mock)
[ ] I test sono isolati? (no dipendenze tra test)
[ ] I nomi dei test descrivono il comportamento atteso?
[ ] I test falliscono correttamente se implementazione e errata?
`;
// STEP 5: Aggiungi test mancanti
// Usa mutation report per identificare mutanti non uccisi
// Aggiungi test mirati per i mutanti sopravvissuti
Validați testele AI cu testarea mutațiilor
Cel mai fiabil mod de a verifica dacă testele generate de AI au valoare reală este efectuați testarea mutațiilor asupra lor:
// stryker.config.js — configurazione per analizzare test AI-generated
/** @type {import('@stryker-mutator/api/core').PartialStrykerOptions} */
module.exports = {
testRunner: 'vitest',
coverageAnalysis: 'perTest',
mutate: [
// Muta solo i file per cui stiamo analizzando i test
'src/services/payment.service.ts',
'src/utils/pricing.ts'
],
vitest: {
configFile: 'vitest.config.ts'
},
thresholds: {
high: 80,
low: 60,
break: 50 // Fallisce la build se mutation score scende sotto 50%
},
reporters: ['html', 'json', 'clear-text'],
htmlReporter: {
fileName: 'reports/mutation-report.html'
}
};
Riscuri și limite ale generării testelor AI
- Teste care testează implementarea: AI tinde să reproducă logica de cod în teste în loc să verifice comportamentul. Examinați testele care arată „oglindă” codului sursă
- Lipsa cunoștințelor domeniului: AI nu cunoaște regulile de afaceri a domeniului dvs. specific. Testele critice de logica de afaceri trebuie scrise sau revizuite de la un dezvoltator cu context
- Falsă asigurare: Testele generate care trec nu înseamnă teste utile. Efectuați întotdeauna testarea mutațiilor înainte de a lua în considerare acoperirea completă
- Halucinații în instalații: AI poate genera date de testare care arată ca valide, dar nu sunt (date imposibile, numere în afara intervalului, e-mailuri formal valid dar incorect din punct de vedere semantic)
Concluzii
Generarea testelor AI este un instrument puternic atunci când este utilizat corect: accelerează scrierea de boilerplate, generează carcase de margine care sunt ușor de uitat și coboară bariera psihologie la testare. Dar necesită un flux de lucru de validare - testarea și revizuirea mutațiilor manual — pentru a se asigura că testele generate au cu adevărat valoare.
Regula de bază: folosește AI pentru a genera 80% din boilerplate și cazuri evidente; Scrieți cei 20% care necesită cunoștințe de domeniu.







