Guadagni:
- Capacità di impedire all'intelligenza artificiale di accettare comportamenti errati come "corretti" calcolando il valore atteso nei test unitari indipendentemente dalla regola di accettazione
- Capacità di stampare test veloci, indipendenti e ripetibili applicando i principi AAA e FIRST e deridendo le dipendenze esterne
- Capacità di testare test con mutazione (rottura del codice) e riconoscere il codice difficile da testare come un odore di progettazione
Il livello più ampio e veloce della piramide dei test è il test unitario, ovvero il test che verifica una funzione o una piccola parte di codice isolatamente da tutto il resto. Migliaia di unit test vengono eseguiti in pochi secondi e rilevano un bug mentre il codice è ancora sullo schermo dello sviluppatore. L’intelligenza artificiale (AI) è forse la più abile nel produrre test unitari: le dai una funzione, l’IA produce dozzine di test. Ma proprio questa comodità dà origine alla trappola più grande: l’intelligenza artificiale produce facilmente test che “si illuminano di verde ma non verificano nulla” o accettano il comportamento attuale (forse difettoso) del codice come “corretto”. In questa unità imparerai come scrivere unit test veramente protettivi con l'intelligenza artificiale e la relazione tra codice testabile e intelligenza artificiale.
Qualità di un buon unit test: PRIMO
I buoni test unitari seguono i principi PRIMI: Veloce, Indipendente (i test non dovrebbero dipendere l'uno dall'altro), Ripetibile (ripetibile - stesso risultato in qualsiasi ambiente), Auto-validante (superato/fallito), Tempestivo (puntuale). Ricordati di questi principi quando chiedi all’intelligenza artificiale di produrre test; chiediamo espressamente che il test non dipenda dal mondo esterno (database reale, rete, orologio) per essere “indipendente” e “ripetibile”.
Modello AAA e asserzione espressiva
Un test unitario solido segue la struttura AAA: Arrange (preparare: impostare input e dipendenze), Act (eseguire: chiamare la funzione sotto test), Assert (convalidare: confrontare il risultato con il valore previsto). Quello critico è affermare. L'errore più comune commesso dall'intelligenza artificiale è derivare l'asserzione dall'output del codice in prova: la logica "qualunque cosa restituisca il codice è vera". Ciò rende il test privo di significato. Il modo corretto è determinare il valore atteso in modo indipendente (calcolarlo manualmente dai criteri di accettazione).
Attenzione: se dici all'AI "scrivi un test per questa funzione", l'AI potrebbe eseguire la funzione e scrivere il suo output come "previsto". Questo test viene superato anche se la funzione è falsa. Invece, dì "calcoli i risultati attesi secondo queste regole, non fare riferimento all'output corrente della funzione".
Mock, stub e dipendenze
Il test unitario richiede l'isolamento. Se la tua funzione dipende da un database o da un'API, questi vengono sostituiti con oggetti fittizi (mock/stub — un sostituto controllato e fittizio della dipendenza reale) durante i test. Ciò rende il test rapido, indipendente e riproducibile. L’intelligenza artificiale può produrre installazioni fittizie; Ma attenzione alle eccessive prese in giro: se si prende in giro tutto, il test verificherà solo "ciò che la simulazione restituisce", non la logica effettiva. Equilibrio: emula il mondo esterno, esegui la logica reale sotto test.
Testabilità e intelligenza artificiale
C'è un feedback interessante: il codice difficile da testare è spesso codice mal progettato. Se l'intelligenza artificiale ha problemi a scrivere test su una funzione (troppe dipendenze, stato globale nascosto, effetti collaterali), si tratta di un odore di design. Chiedere all’IA “come rifattorizzeresti questo codice per renderlo testabile” porta sia a test migliori che a un codice migliore.
Test parametrizzati e diversità dei dati
Scrivere ogni volta un test separato per verificare la stessa regola con input diversi è noioso e difficile da mantenere. Il test parametrizzato – una struttura che esegue ripetutamente la stessa logica di test su un elenco di input e risultati attesi – elimina questa ripetizione: un singolo corpo di test viene alimentato con dozzine di coppie di input. L'intelligenza artificiale è molto efficiente nel produrre queste tabelle dei risultati attesi dagli input quando le vengono fornite le regole di accettazione; In particolare, tabula sistematicamente i valori limite e le classi di equivalenza.
Ma anche qui c’è una trappola: l’IA tende a ricavare i risultati attesi nella tabella generata dal codice in prova. Questo errore è ancora più pericoloso nei test parametrizzati, perché una singola logica errata invalida decine di righe. Pertanto, è necessario calcolare sempre la colonna dei risultati attesi in modo indipendente in base alla regola di accettazione e convalidare manualmente almeno alcune righe. Richiedi anche una colonna di descrizione "cosa rappresenta ogni riga"; quindi quando una riga si interrompe puoi vedere immediatamente quale stato è interrotto.
Suggerimento: aggiungere intenzionalmente una "riga trap" alla tabella di test parametrizzata, ovvero digitare consapevolmente in modo errato il risultato. Se la linea non diventa rossa quando esegui il test, il test non sta effettivamente verificando quella situazione. Questo è un rapido controllo di passaggio simulato.
Prompt debole / Prompt forte
Debole: "Scrivi un test unitario per questa funzione."
Forte: scrivere test unitari [linguaggio/struttura] per la funzione "taxCalculate(amount, rate). Regola di accettazione: risultato = importo * tasso, arrotondato a 2 decimali; importo o tasso negativo genera un errore; restituisce 0 se il tasso è 0. Utilizza la struttura AAA. Calcola manualmente i valori attesi secondo QUESTE regole; non fare riferimento all'output corrente della funzione. Copri i casi limitati e negativi (0, negativo, molto grande, arrotondato ai decimali). Lascia che il nome di ciascun test descriva la regola. verifica. Dipendenza esterna "No."
Prompt potente; Fornisce la regola di accettazione, il valore atteso indipendente, la struttura e i casi limite. Il test diventa così il custode della regola e non lo specchio del codice.
Tabella della qualità dei test unitari
sintomo
Test errato (fiducia falsa)
buona prova
affermare
Nessuno o "non nullo"
Valore concreto atteso
Origine del valore atteso
Uscita della funzione
Regola di accettazione/calcolo manuale
dipendenza
DB/rete/ora effettivi
Isolato con finto/stub
caso limite
Solo strada felice
limite, negativo, errore
Quando infrangi il codice
rimane verde
diventa rosso
Nome
test1, metodo di prova
descrive la regola che conferma
Quattro modelli copiabili
1) Test unitari guidati da regole:
Il tuo ruolo: ingegnere senior di test del software. Scrivi un test unitario sulla seguente funzione con [linguaggio/framework]: [firma]. Regole di accettazione: [regole]. - Utilizza la struttura AAA. - Calcola manualmente i valori attesi secondo QUESTE regole; NON fare riferimento all'uscita corrente della funzione. - Coprire il limite, il negativo, l'errore e il percorso felice con test separati. - Lascia che il nome di ciascun test descriva la regola che verifica. - Simulare le dipendenze esterne; Fai funzionare la logica vera e propria.
2) Controllo della resistenza alla mutazione:
Dai un'occhiata a questi test unitari. Elenca 5 piccole modifiche che potrei apportare al codice da testare (a - invece di +, a >= invece di >, uno spostamento di confine) e dimmi per ognuna QUALE di questi test diventerà rosso? Se non ne viene restituito nessuno, il test è insufficiente.Codice + test: [incolla]
3) Revisione della testabilità:
Perché è difficile scrivere un test unitario per questa funzione? Dipendenza nascosta, status globale, effetti collaterali, ci sono molte responsabilità? Suggerire un refactoring minimo per renderlo testabile; non cambiare comportamento. Codice: [incolla]
4) Completamento dello scenario incompleto:
Vengono fornite le seguenti funzioni e test disponibili. Elenca quali comportamenti/casi limite non sono MAI stati testati (gap di ambito) e aggiungi un test per ciascuno. Funzione+test: [incolla]
tre mini custodie
Caso 1: testare il mirroring del codice. Uno sviluppatore ha chiesto all'IA di scrivere un test per la funzione di arrotondamento; 10 test erano verdi. In effetti, la funzione arrotondava nella direzione sbagliata, ma l'IA aveva preso i valori attesi dall'output della funzione, quindi i test hanno considerato l'errore "vero". Quando i valori attesi sono stati calcolati manualmente con il modello "rule-driven", 4 test sono diventati rossi ed è stato rivelato il vero errore.
Caso 2 – Il valore del controllo della mutazione. Una squadra ha fatto affidamento su 45 test unitari. Ho provato 20 piccole modifiche al codice con un "controllo della robustezza della mutazione"; i test ne hanno individuati solo 11. Le restanti 9 interruzioni sono passate silenziosamente. La squadra ha rafforzato i test deboli; Un errore di calcolo effettivo è stato rilevato da questi test avanzati nella versione successiva.
Caso 3 – L’intestabilità è un odore di design. L'intelligenza artificiale non poteva scrivere test per una funzione di ordinamento, aveva costantemente bisogno del database reale. Il modello di "revisione della testabilità" ha mostrato che la funzione ha incorporato l'accesso al database. Quando l'inserimento delle dipendenze è stato rimosso, è stato possibile scrivere i test e il codice è diventato più pulito.
Errori comuni
- Derivare il valore atteso dal codice. L'IA accetta l'output della funzione come "corretto"; test che confermi il codice difettoso.
- Prova senza asserzione o con asserzione banale. "Non ha commesso un errore, ha superato" la logica; Non conferma nulla.
- Derisione estrema. Deridere tutto e testare solo ciò che la finzione restituisce; la logica reale non viene testata.
- Solo la strada felice. Superamento degli stati limite, negativo ed errore.
- Non testare infrangendo il codice. Fidarsi del verde senza verificare la mutazione.
- Ignorando l'intestabilità. Non riconoscere e correggere la cattiva progettazione invece di spingere test rigorosi.
In sintesi
I test unitari sono il livello più veloce e più grande della piramide dei test; Coglie l'errore nel momento più conveniente. L'intelligenza artificiale è molto capace di produrre test unitari, ma la sua più grande trappola è scrivere test che assumono un comportamento errato come "corretto" derivando il valore atteso dal codice stesso. Soluzione: fornire le regole di accettazione, far calcolare manualmente i valori attesi, applicare i principi AAA e FIRST, deridere il mondo esterno ed eseguire la logica effettiva e testare ogni test mediante mutazione (infrazione del codice). Il codice difficile da testare è un segno di progettazione che deve essere corretto.
Compito dell'applicazione
Seleziona una funzione che contiene una regola aziendale dal tuo progetto. Scrivere regole di accettazione e far scrivere all’IA i test con il modello “rule-driven unit testing”; Far calcolare manualmente i valori attesi. Quindi applica il “controllo della robustezza della mutazione”: fai almeno 5 piccole interruzioni nel codice e misura quanti test diventano rossi. Aggiungi un nuovo test per le corruzioni non rilevate. Riporta quante interruzioni sono state rilevate (come il punteggio di mutazione).
lista di controllo
- [ ] Ho fornito le regole di accettazione e ho fatto calcolare manualmente i valori attesi.
- [ ] Mi sono assicurato che i test non ricavassero il valore atteso dal codice.
- [ ] Ho stabilito test indipendenti seguendo le linee guida AAA e FIRST.
- [ ] Ho deriso le dipendenze esterne e ho eseguito la logica effettiva.
- [ ] Ho trattato casi limite, negativi ed errori.
- [ ] Decriptando il codice (mutazione) ho dimostrato che i test effettivamente proteggono.