Table of Contents
Nel software di ingegneria, garantire test completi è fondamentale per l'affidabilità, la sicurezza e la conformità alle normative. Gli strumenti di copertura del codice sono essenziali per identificare i percorsi non testati nella base di codice - le sequenze specifiche di codice che non vengono mai eseguite durante la vostra suite di test.
Cosa sono gli strumenti di copertura del codice?
Gli strumenti di copertura del codice sono strumenti software che monitorano quali parti del codice sorgente vengono eseguite quando si esegue la suite di prova. Essi lavorano strumentalizzando il codice - inserendo sonde o contatori - sia in fase di compilazione (per le lingue compilate) o in tempo di esecuzione (per le lingue interpretate). Dopo l'esecuzione dei test, lo strumento aggrega i dati di esecuzione e produce un rapporto di copertura che mostra la percentuale di codice esercitato, insieme a una dettagliata ripartizione delle linee, rami e percorsi.
L'obiettivo primario è quello di misurare la completezza dei test, ma gli strumenti di copertura evidenziano anche direttamente il codice non testato.Quando una funzione, ramo condizionale, o percorso logico non viene mai visitato, appare come scoperto nel rapporto.
Per il software di ingegneria scritto in C/C++, gli strumenti come gcov] e ]BullseyeCoverage sono comuni per i sistemi basati su Java ] JaCo è lo stesso standard di fatto.
Tipi di copertura e loro importazione
La copertura del codice non è una singola metrica. Diversi tipi di copertura rivelano diversi aspetti della completezza del test. Per il software di ingegneria - dove la sicurezza e la correttezza sono fondamentali - la comprensione della distinzione è fondamentale.
Copertura della linea
La copertura della linea (chiamata anche copertura di dichiarazione) misura la percentuale di linee esecubili di codice che sono state eseguite durante i test. È la più semplice metrica e spesso la più ampiamente segnalato. Se una linea non è mai eseguita, è un percorso ovvio non testato. Tuttavia, la copertura della linea può essere fuorviante: un test potrebbe eseguire ogni linea ma ancora perdere il comportamento pericoloso perché un ramo condizionale non è mai stato preso.
Copertura del ramo
La copertura del ramo misura se ogni possibile risultato di decisione (true/false per , caso per , uscite del loop) è stato esercitato. In C/C++ e Java, la copertura del ramo è generalmente espressa come percentuale di tutti i rami. I rami non testati sono percorsi non testati che possono nascondere errori di logica.
Copertura del percorso
Per una funzione con più condizioni nidificate, il numero di percorsi cresce esponenzialmente (esplosione del percorso). In pratica, la copertura del percorso è spesso approssimata combinando la copertura di branch e di stato.
Copertura delle condizioni (MC/DC)
La copertura delle condizioni assicura che ogni sottoespressione booleana (condizione) in una decisione sia stata valutata sia allineare che al falso. MC/DC va oltre richiedendo che ogni condizione cambi in modo indipendente l'esito della decisione. Questa è la forma più rigorosa di copertura per il software di ingegneria critica della sicurezza e espone direttamente percorsi non testati attraverso la logica complessa.
La comprensione di questi tipi di copertura permette ai team di scegliere la giusta metrica per il loro livello di certificazione e il profilo di rischio.Per i sistemi ad alta intensità, affidarsi esclusivamente alla copertura di linea è pericoloso; rami e percorsi non testati possono portare a fallimenti catastrofici.
Perché identificare i percorsi non testati?
I percorsi non testati rappresentano sequenze di codice che non sono mai state convalidate. Nel software di ingegneria, sistemi di controllo incorporati, motori di simulazione o firmware di dispositivi medici, questi vuoti possono causare guasti che portano a rischi di sicurezza, degrado delle prestazioni o non conformità normativa.
- Therac-25 (1980s): Una radioterapia non è riuscita a causa di una condizione di gara nel suo software di controllo che non era mai stato testato sotto determinate sequenze operative. Il percorso di codice che ha permesso l'errore è stato scoperto da test ma solo dopo un incidente mortale.
- Mars Climate Orbiter (1999):[] Un percorso di codice di navigazione che le unità metriche e imperiali miste non sono mai state esercitate nei test di terra.
- L'accelerazione non voluta di Toyota (2009):[ I percorsi di codice critici nell'ECU non sono stati testati in condizioni reali, portando ad un richiamo di milioni di veicoli.
Identificare percorsi non testati prima del rilascio è una strategia di mitigazione del rischio proattiva. Aiuta anche a soddisfare i revisori normativi: standard come ISO 26262, DO-178C e IEC 62304 richiedono analisi di copertura strutturale come parte del processo di verifica.
Utilizzo di strumenti di copertura per trovare percorsi non testati
Il flusso di lavoro pratico per identificare percorsi non testati comporta diversi passaggi, a partire dalla strumentazione e termina con la creazione di test mirata.
Strumentazione e esecuzione dei test
Per gcov, compilate con ]. Per JaCoCo, utilizzate l'agente tramite la bandiera []. Eseguire la vostra suite di prova completa. Gli strumenti che il codice viene colpito e scrive i file di dati grezzi (ad esempio, ] per gcov, per JaCoCoCo.
Generare e rivedere i report di copertura
Utilizzare il comando di report dello strumento (ad esempio, , ) per produrre report HTML o XML. Queste relazioni righe di codice colore (verde = hit, rosso = non colpito) e elenco rami scoperti. Focus first su funzioni o moduli con percentuali di copertura basse. Per ogni riga o ramo scoperto, chiedere: È questo codice raggiungibile in qualsiasi condizione? Se sì, rappresenta un percorso.
Analizzare i percorsi non testati
Non tutti i percorsi non testati sono altrettanto importanti. Prioritize:
- Codice di gestione dell'orrore[[] (ad esempio, i gestori delle eccezioni, le routine di ricaduta) — spesso lasciato non testato ma critico per il funzionamento sicuro.
- Casi di copertura e condizioni di confine[[[] – loop che non cancellano mai, indici di array ai limiti, casi di default nelle dichiarazioni di commutazione.
- Funzioni correlate alla sicurezza[[] — codice che monitora i sensori, attua le uscite o verifica gli invarianti.
Usare report di copertura per identificare sequenze specifiche: un ramo rosso all'interno di un nido [] indica un percorso che non accade mai in alcun test.
Strumenti di copertura popolari per il software di ingegneria
La scelta dello strumento giusto dipende dai requisiti di lingua, piattaforma e copertura.
gcov (C/C++)
gcov è lo strumento di copertura GNU in bundle con GCC. Fornisce copertura linea e ramo ed è fonte libera e aperta. Si integra bene con sistemi di costruzione come CMake e può essere utilizzato in cross-compilazione per obiettivi incorporati. Documentazione ufficiale gcov] spiega come generare report.
JaCoCo (Java)
JaCoCo è la libreria di copertura standard del settore per Java. Offre copertura linea, ramo e metodo. Il suo agente può collegare a eseguire JVM senza modifiche di codice. Per i sistemi di ingegneria costruiti su Java (ad esempio, SCADA o framework di simulazione), JaCo è altamente efficace. JaCo sito web]] ha guide di configurazione dettagliate.
BullseyeCoverage (C/C++)
BullseyeCoverage è uno strumento commerciale che fornisce funzionalità, branch e copertura delle condizioni (compresi MC/DC), progettato per lo sviluppo critico e incorporato della sicurezza. I suoi rapporti mostrano esattamente quali condizioni all'interno delle espressioni sono non testate. Molte squadre in aerospaziale e automobilistico si affidano a BullseyeCoverage per la conformità DO-178C e ISO 26262.
Altri strumenti
- OpenCppCoverage (Windows, C/C++)[] — uno strumento open-source gratuito che si integra con Visual Studio e offre una copertura di branch.
- Coverage.py (Python)[ – per gli script di ingegneria basati sui dati scritti in Python, questo strumento fornisce la copertura di linea e di ramo.
- La copertura integrata di Go[ – Go's [] fornisce la copertura di linea e dichiarazione, con supporto di branch sperimentale.
Molte squadre utilizzano anche servizi di aggregazione basati su cloud come []Codecov o SonarQube] per visualizzare le tendenze di copertura e le richieste di gate pull.
Integrazione della copertura nel flusso di lavoro di sviluppo
Identificare percorsi non testati dovrebbe essere un'attività continua, non un audit di una volta.
- Run copertura su ogni commit[ – anche parziale copertura dà un feedback rapido.
- Imposta le soglie di copertura minime[[] — non riescono a costruire se la copertura scende sotto un livello configurabile (ad esempio, la copertura di branch 80% per i moduli critici).
- I rapporti di copertura generici come artefatti[] — li rendono accessibili a tutti gli sviluppatori.
- Create coverage diffs[ – strumenti come Codecov mostrano che linee una nuova richiesta pull tocca che sono stati non testati, costringendo gli sviluppatori ad aggiungere test per modifiche scoperte.
- Gate si fonde su percorsi non testati[[] – per software ad alta intensità, richiedono una copertura al 100% MC/DC per funzioni critiche alla sicurezza prima di fondersi.
L'automazione rimuove l'onere dell'ispezione manuale. Gli sviluppatori possono vedere i percorsi non testati evidenziati nel loro editor o nel cruscotto CI e scrivere test immediatamente.
Migliori Pratiche per un uso efficace
Per ottenere il massimo dagli strumenti di copertura del codice per trovare percorsi non testati, seguire queste pratiche:
- Combina diversi tipi di copertura[[[] — la copertura della linea da sola può essere ingannevole.
- Focus su codice ad alto rischio[[] — funzioni complesse di destinazione, maneggiatori di errori e routine sensibili alla sicurezza.
- Utilizzare l'analisi statica a fianco della copertura[[[] — l'analisi statica può trovare un codice non raggiungibile che gli strumenti di copertura possono mancare (ad esempio, il codice morto non eseguito a causa di errori logici).
- Copertura di misura in condizioni realistiche[[] – utilizzare test di livello del sistema e integrazione, non solo test di unità.
- Copertura di fattura per la copertura[[] – test di scrittura che artificialmente sollevano la copertura senza convalidare il comportamento (ad esempio, test di getters triviali / setrs) rifiuti di sforzo.
- Riguarda le tendenze di copertura nel tempo[[[] – una tendenza di copertura in diminuzione indica che viene aggiunto un nuovo codice senza i test corrispondenti, creando nuovi percorsi non testati.
- Istruire il team[[] – aiuta gli sviluppatori a capire che i report di copertura non sono un giudizio ma uno strumento per trovare le lacune.
Sfide e limitazioni
Mentre potenti, gli strumenti di copertura del codice hanno limitazioni che le squadre devono riconoscere:
- Overhead[[] — la strumentazione può rallentare l'esecuzione dei test e aumentare le dimensioni binarie. Per i sistemi incorporati con memoria stretta, questo può essere problematico. La strumentazione a tempo pieno a tempo pieno ha spesso un minimo di runtime in testa ma richiede un'attenta configurazione.
- Confidenza di fondo[[] — l'alta copertura non significa test perfetti. I test potrebbero esercitare il codice ma non controllare i risultati correttamente. Combinare la copertura con la densità di asserzione e il test di mutazione.
- Effetto del pavimento[] — per codice altamente complesso con molte condizioni, la copertura del percorso è computazionalmente infesibile.
- Instrumentazione nella produzione[[] – la maggior parte degli strumenti di copertura sono progettati per il test di sviluppo.
- Limitazioni di linguaggio e ambiente[[[] – alcuni obiettivi incorporati non hanno strumenti di copertura robusti, soprattutto per l'assemblaggio o hardware personalizzato.
Nonostante queste sfide, la copertura del codice rimane uno dei modi più efficaci per identificare i percorsi non testati. La chiave è quella di utilizzare gli strumenti in modo intelligente e combinarli con altri metodi di verifica.
Conclusioni
Gli strumenti di copertura del codice sono indispensabili per i team di software di ingegneria che devono garantire ogni percorso critico è testato. Rivelando linee, rami e condizioni non testate, forniscono un modo di focalizzare gli sforzi di test in cui si contano più. Quando integrato nei flussi di lavoro CI/CD e combinato con analisi statiche e priorità basata sui rischi, l'analisi della copertura aiuta a prevenire i bug nascosti che possono portare a guasti nel campo.