Contenuto principale

La traduzione di questa pagina non è aggiornata. Fai clic qui per vedere l'ultima versione in inglese.

Verifica di un algoritmo di MATLAB utilizzando test basati sui requisiti

Questo esempio mostra come verificare un algoritmo di MATLAB® creando collegamenti di verifica dalle righe di codice MATLAB nelle funzioni e nei test ai requisiti. Questo esempio utilizza un progetto che contiene un algoritmo per calcolare il percorso più breve tra due nodi su un grafico.

Aprire il progetto ShortestPath.

openProject("ShortestPath");

Esame degli artefatti del progetto

Il progetto comprende:

  • Insiemi di requisiti per i requisiti funzionali e di test, situati nella cartella requirements

  • Un algoritmo di MATLAB, situato nella cartella src

  • I test unitari MATLAB, situati nella cartella tests

  • Collegamenti dalle righe di codice MATLAB ai requisiti, file .slmx memorizzati, situati nelle cartelle src e tests

  • Script per automatizzare l'analisi del progetto, situati nella cartella scripts

Apertura dell'insieme di requisiti funzionali

L'insieme di requisiti shortest_path_func_reqs acquisisce il comportamento funzionale richiesto dalla funzione shortest_path. I requisiti descrivono il comportamento nominale e il comportamento previsto in condizioni non valide, ad esempio quando gli input della funzione non sono validi. Aprire l'insieme di requisiti nell'Editor dei requisiti.

funcReqs = slreq.open("shortest_path_func_reqs");

Utilizzo della funzione percorso più breve

La funzione shortest_path verifica la validità degli input della funzione, quindi utilizza l'algoritmo di Djikstra per calcolare il numero di archi nel percorso più breve tra due nodi su un grafico. Gli input della funzione sono una matrice di adiacenza che rappresenta un grafico, il nodo iniziale e il nodo finale. Si consideri, ad esempio, questa matrice di adiacenza che rappresenta un grafico con sei nodi.

A = [0 1 0 0 1 0;
    1 0 1 0 0 0;
    0 1 0 1 0 0;
    0 0 1 0 1 1;
    1 0 0 1 0 0;
    0 0 0 1 0 0];

Creare un grafico dalla matrice e tracciarlo.

G = graph(A);
plot(G,EdgeLabel=G.Edges.Weight)

Figure contains an axes object. The axes object contains an object of type graphplot.

Calcolare il numero di archi nel percorso più breve tra i nodi 1 e 6.

pathLength = shortest_path(A,1,6)
pathLength = 3

Apertura dell'insieme di requisiti di test

L'insieme di requisiti shortest_path_tests_reqs contiene i requisiti di test che descrivono il comportamento funzionale che deve essere testato da un caso di test. I requisiti di test sono derivati dai requisiti funzionali. Sono disponibili requisiti di test per il comportamento nominale e per le condizioni non valide. Aprire l'insieme di requisiti nell'Editor dei requisiti.

testReqs = slreq.open("shortest_path_tests_reqs");

I test unitari MATLAB basati su classi in graph_unit_tests implementano i casi di test descritti in shortest_path_tests_reqs. La classe contiene metodi di test basati sui requisiti di test da shortest_path_tests_reqs. La classe contiene inoltre il metodo verify_path_length, che i casi di test utilizzano come metodo di qualificazione per verificare che i risultati attesi e quelli effettivi siano uguali. La classe contiene inoltre metodi statici che creano matrici di adiacenza per i casi di test.

Visualizzazione dello stato della verifica

Per visualizzare lo stato della verifica, nella barra degli strumenti Editor dei requisiti, nella sezione View (Vista), fare clic su showColumns_16.pngColumns (Colonne) e selezionare Verification Status (Stato della verifica). Tre dei requisiti funzionali e un requisito di test non dispongono di collegamenti di verifica. Lo stato della verifica è giallo per ogni requisito, a indicare che i test collegati non sono stati eseguiti.

missingVerification.png

Eseguire i test e aggiornare lo stato della verifica per gli insiemi di requisiti utilizzando il metodo runTests.

status1 = runTests(funcReqs);
Running graph_unit_tests
.......... ..
Done graph_unit_tests
__________
status2 = runTests(testReqs);
Running graph_unit_tests
.......... ...
Done graph_unit_tests
__________

Lo stato della verifica è verde, a indicare che i test collegati sono stati superati. Tuttavia, alcuni dei requisiti non hanno collegamenti ai test.

Identificazione delle lacune di tracciabilità nel progetto

I requisiti funzionali e di test sono collegati alle righe di codice nei file shortest_path e graph_unit_tests, ma la tracciabilità non è completa. Utilizzare una matrice di tracciabilità per identificare i requisiti che non sono collegati ai test e per creare collegamenti che rendano i requisiti completamente tracciabili.

Identificazione dei collegamenti mancanti tramite una matrice di tracciabilità

Creare una matrice di tracciabilità per entrambi gli insiemi di requisiti con i requisiti in alto e i test unitari a sinistra. Per maggiori informazioni sulle matrici di tracciabilità, vedere Track Requirement Links with a Traceability Matrix

mtxOpts = slreq.getTraceabilityMatrixOptions;
mtxOpts.topArtifacts = {'shortest_path_func_reqs.slreqx','shortest_path_tests_reqs.slreqx'};
mtxOpts.leftArtifacts = {'graph_unit_tests'};
slreq.generateTraceabilityMatrix(mtxOpts)

Nel Filter Panel (Pannello filtro), nella sezione Top (Top), filtrare la matrice per mostrare solo i requisiti funzionali non collegati ai test facendo clic su:

  • Top (Top) > Link (Collegamento) > Missing Links (Collegamenti mancanti)

  • Top (Top) > Type (Tipo) > Functional (Funzionale)

Nella sezione Left (Sinistra), mostrare solo le funzioni di test nel file graph_unit_tests facendo clic su:

  • Left (Sinistra) > Type (Tipo) > Function (Funzione)

  • Left (Sinistra) > Attributes (Attributi) > Test (Test)

Fare clic su Highlight Missing Links (Evidenzia collegamenti mancanti) nella barra degli strumenti.

missingLinksTRMX.png

La finestra della matrice di tracciabilità mostra i tre requisiti funzionali e un requisito di test che non dispongono di collegamenti di verifica.

Creazione dei collegamenti di verifica per i requisiti

Il requisito di test 2.1.3, Test for a graph that is a tree, non è collegato a un test. Un albero è un grafico in cui due nodi qualsiasi sono collegati da un unico percorso.

Il caso di test check_invalid_start_1 testa un grafico ad albero utilizzando il metodo statico graph_straight_seq per creare la matrice di adiacenza. Utilizzare il metodo graph_straight_seq per visualizzare il grafico ad albero.

A = graph_unit_tests.graph_straight_seq;
G = graph(A);
plot(G,EdgeLabel=G.Edges.Weight)

Figure contains an axes object. The axes object contains an object of type graphplot.

Creare un collegamento dal requisito Test for a graph that is a tree al caso di test check_invalid_start_1 utilizzando la matrice di tracciabilità generata in precedenza.

slreq.generateTraceabilityMatrix(mtxOpts)

Fare clic sulla cella corrispondente al requisito e al test e selezionare Create (Crea). Nella finestra di dialogo Create Link (Crea collegamento), fare clic su Create (Crea).

createTestLink.png

Aggiornare lo stato della verifica nell'Editor dei requisiti eseguendo i test collegati ai requisiti di test. Il test check_invalid_start_1 verifica il requisito Test for a graph that is a tree.

status3 = runTests(testReqs);
Running graph_unit_tests
.......... ...
Done graph_unit_tests
__________

Inoltre, tre requisiti funzionali non hanno collegamenti ai test:

  • Requisito 2.2.1: Returns -9 for invalid adjacency matrices

  • Requisito 2.2.2: Returns -19 if the start node is encoded incorrectly

  • Requisito 2.2.3: Returns -29 if end node is encoded incorrectly

È presenta una lacuna di tracciabilità per questi requisiti. Non è possibile colmare questa lacuna creando collegamenti ai test, poiché non esistono test che verificano tali requisiti.

Correzione delle lacune della coverage e di tracciabilità creando test

I tre requisiti funzionali che non hanno collegamenti ai test, presentano collegamenti alle righe di codice nella funzione shortest_path. Eseguire i test con coverage per determinare se quelle righe di codice nella funzione shortest_path sono coperte dai test.

Esecuzione di test con coverage

Utilizzare lo script RunTestsWithCoverage per eseguire i test con coverage delle funzioni e delle dichiarazioni e visualizzare la coverage in un report. Per maggiori informazioni, vedere Collect Statement and Function Coverage Metrics for MATLAB Source Code.

RunTestsWithCoverage
Running graph_unit_tests
.......... ....
Done graph_unit_tests
__________

MATLAB code coverage report has been saved to:
 C:\Users\ahoward\AppData\Local\Temp\tpc3b346ea_31dd_409d_be4c_5e787898bf8f\index.html

Aprire il report sulla coverage. Le dichiarazioni relative ai codici di errore alle righe 20, 25 e 30 non sono coperte dai test.

missingCoverage.png

Si noti che la lacuna di coverage di queste righe di codice e la lacuna di tracciabilità dei requisiti 2.2.1, 2.2.2 e 2.2.3 si riferiscono agli stessi codici di errore. È possibile colmare contemporaneamente le lacune di coverage e di tracciabilità creando test per queste righe di codice e creando collegamenti ai requisiti.

Miglioramento della coverage creando nuovi test

Creare test che migliorino la coverage dei test e verificare i requisiti 2.2.1, 2.2.2 e 2.2.2. Aprire il file di test graph_unit_tests.

open("graph_unit_tests.m");

Queste funzioni testano i tre codici di errore. Copiare e incollare il codice nella riga 4, nella sezione dei metodi di test del file graph_unit_tests, quindi salvarlo.

function check_invalid_nonsquare(testCase)
    adjMatrix = zeros(2,3);
    startIdx = 1;
    endIdx = 1;
    expOut = -9;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'Graph is not square');
end

function check_invalid_entry(testCase)
    adjMatrix = 2*ones(4,4);
    startIdx = 1;
    endIdx = 1;
    expOut = -9;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'Adjacency matrix is not valid');
end

function check_invalid_noninteger_startnode(testCase)
    adjMatrix = zeros(4,4);
    startIdx = 1.2;
    endIdx = 1;
    expOut = -19;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'Start node is not an integer');
end

function check_invalid_noninteger_endnode(testCase)
    adjMatrix = zeros(4,4);
    startIdx = 1;
    endIdx = 2.2;
    expOut = -29;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'End node is not an integer');
end

Eseguire nuovamente i test con coverage e aprire il report sulla coverage.

RunTestsWithCoverage
Running graph_unit_tests
.......... ....
Done graph_unit_tests
__________

MATLAB code coverage report has been saved to:
 C:\Users\ahoward\AppData\Local\Temp\tpd094de61_604e_45b4_8b53_767a6f4719cb\index.html

I test ora coprono le dichiarazioni dei codici di errore.

improvedCoverage.png

Tuttavia, alla riga 97 è riportata una dichiarazione che i test non coprono. Le condizioni che richiedono che i test coprano la dichiarazione alla riga 97 comportano anche l'esecuzione di return alla riga 87, il che significa che la dichiarazione alla riga 97 non è raggiungibile ed è logica morta.

deadLogic.png

Risoluzione delle lacune di tracciabilità dei requisiti

Rigenerare la matrice di tracciabilità, applicare gli stessi filtri di prima, quindi fare clic su Highlight Missing Links (Evidenzia collegamenti mancanti) nella barra degli strumenti.

slreq.generateTraceabilityMatrix(mtxOpts)
  • Top (Top) > Link (Collegamento) > Missing Links (Collegamenti mancanti)

  • Top (Top) > Type (Tipo) > Functional (Funzionale)

  • Left (Sinistra) > Type (Tipo) > Function (Funzione)

  • Left (Sinistra) > Attributes (Attributi) > Test (Test)

Creare collegamenti tra i requisiti relativi ai codici di errore e i nuovi test.

createLinksImproveCoverage.png

Aggiornare lo stato di verifica nell'Editor dei requisiti eseguendo nuovamente i test collegati a entrambi gli insiemi di requisiti.

status4 = runTests(funcReqs);
Running graph_unit_tests
.......... ..
Done graph_unit_tests
__________
status5 = runTests(testReqs);
Running graph_unit_tests
.......... ...
Done graph_unit_tests
__________

Tutti i requisiti presentano collegamenti ai test e tutti i test sono stati superati.

updatedVerificationStatus.png

Tracciamento dei requisiti nel codice generato

Utilizzare Embedded Coder® per generare codice dall'algoritmo shortest_path e includere commenti sui requisiti che consentono il loro tracciamento nel codice generato. Per maggiori informazioni, vedere Requirements Traceability for Code Generated from MATLAB Code.

Creare un oggetto di configurazione del codice per generare codice con un tipo di build LIB.

cfg = coder.config("lib","ecoder",true);

Abilitare il parametro di configurazione del codice per includere i commenti sui requisiti nel codice generato.

cfg.ReqsInCode = true;

Utilizzare coder.typeof (MATLAB Coder) per definire un array double di dimensioni variabili con una dimensione massima di 100x100 e uno scalare double da utilizzare come input nel codice generato.

mtxType = coder.typeof(ones(100,100),[],1);
scalarDblType = coder.typeof(1);

Generare codice C dall'algoritmo shortest_path con i parametri di configurazione del codice e i tipi di input specificati. Creare un report sulla generazione di codice e avviarlo.

codegen shortest_path -config cfg -args {mtxType, scalarDblType, scalarDblType} -launchreport
Code generation successful: View report

codegen-report-requirements-comments.png

Il file shortest_path.c contiene commenti con il riepilogo del requisito collegato, il percorso completo del file shortest_path.m e le righe di codice collegate.

Vedi anche

| (MATLAB Coder) | (MATLAB Coder)

Argomenti