Verifizieren eines MATLAB-Algorithmus mithilfe von anforderungsbasierten Tests
Dieses Beispiel zeigt, wie Sie einen MATLAB®-Algorithmus verifizieren, indem Sie Verifikationsverknüpfungen von MATLAB-Programmcodezeilen in Funktionen und Tests zu Anforderungen erstellen. In diesem Beispiel wird ein Projekt verwendet, das einen Algorithmus zur Berechnung des kürzesten Weges zwischen zwei Knoten in einem Graphen enthält.
Öffnen Sie das Projekt ShortestPath
.
openProject("ShortestPath");
Untersuchen der Projektartefakte
Das Projekt umfasst:
Anforderungssätze für funktionale und Testanforderungen, die sich im Ordner
requirements
befindenEinen MATLAB-Algorithmus
src
befindetMATLAB Unit-Tests, die sich im Ordner
tests
befindenVerknüpfungen von MATLAB Programmcodezeilen zu Anforderungen, die in
.slmx
-Dateien in den Ordnernsrc
undtests
gespeichert sindSkripte zur Automatisierung der Projektanalyse, die sich im Ordner
scripts
befinden
Öffnen des funktionalen Anforderungssatzes
Der Anforderungssatz shortest_path_func_reqs
erfasst das funktionale Verhalten, das die Funktion shortest_path
benötigt. Die Anforderungen beschreiben das nominale Verhalten und das erwartete Verhalten bei ungültigen Bedingungen, beispielsweise wenn die Eingaben für die Funktion nicht gültig sind. Öffnen Sie den Anforderungssatz im Requirements Editor.
funcReqs = slreq.open("shortest_path_func_reqs");
Verwenden der Funktion „Shortest Path“
Die Funktion shortest_path
prüft die Gültigkeit der Eingaben für die Funktion und berechnet dann mithilfe des Djikstra-Algorithmus die Anzahl der Kanten im kürzesten Weg zwischen zwei Knoten in einem Graphen. Die Eingaben für die Funktion sind eine Adjazenzmatrix, die einen Graphen darstellt, der Startknoten und der Endknoten. Betrachten Sie beispielsweise diese Adjazenzmatrix, die einen Graphen mit sechs Knoten darstellt.
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];
Erstellen Sie einen Graphen aus der Matrix und plotten Sie ihn.
G = graph(A); plot(G,EdgeLabel=G.Edges.Weight)
Berechnen Sie die Anzahl der Kanten im kürzesten Weg zwischen den Knoten 1 und 6.
pathLength = shortest_path(A,1,6)
pathLength = 3
Öffnen des Testanforderungssatzes
Der Anforderungssatz shortest_path_tests_reqs
enthält Testanforderungen, die das funktionale Verhalten beschreiben, das durch einen Testfall geprüft werden muss. Die Testanforderungen werden aus den funktionalen Anforderungen abgeleitet. Es bestehen Testanforderungen für das nominale Verhalten und für die ungültigen Zustände. Öffnen Sie den Anforderungssatz im Requirements Editor.
testReqs = slreq.open("shortest_path_tests_reqs");
Die klassenbasierten MATLAB Unit-Tests in graph_unit_tests
implementieren die in shortest_path_tests_reqs
beschriebenen Testfälle. Die Klasse enthält Testmethoden, die auf den Testanforderungen aus shortest_path_tests_reqs
basieren. Die Klasse enthält auch die Methode verify_path_length
, die von den Testfällen als Qualifizierungsmethode verwendet wird, um zu überprüfen, ob die erwarteten und tatsächlichen Ergebnisse übereinstimmen. Die Klasse enthält auch statische Methoden, die Adjazenzmatrizen für die Testfälle erstellen.
Anzeigen des Verifikationsstatus
Um den Verifikationsstatus anzuzeigen, klicken Sie in der Symbolleiste Requirements Editor im Abschnitt View auf Columns und wählen Sie Verification Status. Bei drei funktionalen Anforderungen und einer Testanforderung fehlen Verifikationsverknüpfungen. Der Verifikationsstatus ist für jede Anforderung gelb, was darauf hinweist, dass die verknüpften Tests nicht ausgeführt wurden.
Führen Sie die Tests aus und aktualisieren Sie den Verifikationsstatus für die Anforderungssätze mithilfe der Methode runTests
.
status1 = runTests(funcReqs);
Running graph_unit_tests .......... .. Done graph_unit_tests __________
status2 = runTests(testReqs);
Running graph_unit_tests .......... ... Done graph_unit_tests __________
Der Verifikationsstatus ist grün, um anzuzeigen, dass die verknüpften Tests bestanden wurden. Einige der Anforderungen sind jedoch nicht mit Tests verknüpft.
Identifizieren von Lücken in der Rückverfolgbarkeit des Projekts
Die funktionalen und Testanforderungen sind mit Codezeilen in den Dateien shortest_path
und graph_unit_tests
verknüpft, jedoch ist die Rückverfolgbarkeit nicht vollständig gewährleistet. Verwenden Sie eine Rückverfolgbarkeitsmatrix, um Anforderungen zu identifizieren, die nicht mit Tests verknüpft sind, und um Verknüpfungen zu erstellen, damit die Anforderungen vollständig rückverfolgbar sind.
Finden fehlender Verknüpfungen mithilfe einer Rückverfolgbarkeitsmatrix
Erstellen Sie eine Rückverfolgbarkeitsmatrix für beide Anforderungssätze, wobei die Anforderungen oben und die Unit-Tests links aufgeführt sind. Weitere Informationen zu Rückverfolgbarkeitsmatrizen finden Sie unter 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)
Filtern Sie im Filter Panel im Abschnitt Top die Matrix, um nur die funktionalen Anforderungen anzuzeigen, die nicht mit Tests verknüpft sind, indem Sie auf Folgendes klicken:
Top > Link > Missing Links
Top > Type > Functional
Im Abschnitt Left werden nur die Testfunktionen in der Datei graph_unit_tests
angezeigt, indem Sie auf Folgendes klicken:
Left > Type > Function
Left > Attributes > Test
Klicken Sie in der Symbolleiste auf Highlight Missing Links.
Das Fenster „Traceability Matrix“ zeigt die drei funktionalen Anforderungen und eine Testanforderung, für die keine Verifikationsverknüpfungen vorhanden sind.
Erstellen von Verifikationsverknüpfungen für Anforderungen
Die Testanforderung 2.1.3, Test for a graph that is a tree
, ist nicht mit einem Test verknüpft. Ein Baum ist ein Graph, in dem jeweils zwei Knoten nur über einen einzigen Pfad miteinander verbunden sind.
Der Testfall check_invalid_start_1
testet einen Baumgraphen, indem er die statische Methode graph_straight_seq
verwendet, um die Adjazenzmatrix zu erstellen. Verwenden Sie die Methode graph_straight_seq
, um das Baumdiagramm anzuzeigen.
A = graph_unit_tests.graph_straight_seq; G = graph(A); plot(G,EdgeLabel=G.Edges.Weight)
Erstellen Sie mithilfe der zuvor erstellten Rückverfolgbarkeitsmatrix eine Verknüpfung von der Anforderung Test for a graph that is a tree
zum Testfall check_invalid_start_1
.
slreq.generateTraceabilityMatrix(mtxOpts)
Klicken Sie auf die Zelle, die der Anforderung und dem Test entspricht, und wählen Sie Create. Klicken Sie im Dialogfeld „Create Link“ auf Create.
Aktualisieren Sie den Verifikationsstatus im Requirements Editor, indem Sie die mit den Testanforderungen verknüpften Tests ausführen. Der Test check_invalid_start_1
überprüft die Anforderung Test for a graph that is a tree
.
status3 = runTests(testReqs);
Running graph_unit_tests .......... ... Done graph_unit_tests __________
Darüber hinaus sind drei funktionale Anforderungen nicht mit Tests verknüpft:
Anforderung 2.2.1:
Returns -9 for invalid adjacency matrices
Anforderung 2.2.2:
Returns -19 if the start node is encoded incorrectly
Anforderung 2.2.3:
Returns -29 if end node is encoded incorrectly
Es besteht eine Lücke in der Rückverfolgbarkeit dieser Anforderungen. Sie können diese Lücke nicht durch Verknüpfungen zu Tests schließen, da es keine Tests gibt, die diese Anforderungen überprüfen.
Beheben von Lücken in der Abdeckung und Rückverfolgbarkeit durch das Erstellen von Tests
Die drei funktionalen Anforderungen, die keine Verknüpfungen zu Tests aufweisen, sind mit Codezeilen in der Funktion shortest_path
verknüpft. Führen Sie die Tests mit Abdeckung durch, um festzustellen, ob diese Codezeilen in der Funktion shortest_path
von den Tests abgedeckt werden.
Ausführen von Tests mit Abdeckung
Verwenden Sie das Skript RunTestsWithCoverage
, um die Tests mit Funktions- und Anweisungsabdeckung auszuführen und die Abdeckung in einem Bericht anzuzeigen. Weitere Informationen finden Sie unter 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
Öffnen Sie den Abdeckungsbericht. Die Fehlercode-Anweisungen in den Zeilen 20, 25 und 30 werden nicht durch Tests abgedeckt.
Beachten Sie, dass sich die Abdeckungslücke für diese Codezeilen und die Rückverfolgbarkeitslücke für die Anforderungen 2.2.1, 2.2.2 und 2.2.3 auf dieselben Fehlercodes beziehen. Sie können die Lücken in der Abdeckung und Rückverfolgbarkeit gleichzeitig schließen, indem Sie Tests für diese Codezeilen erstellen und Verknüpfungen zu den Anforderungen herstellen.
Verbessern der Abdeckung durch das Erstellen neuer Tests
Erstellen Sie Tests, die die Abdeckung der Tests verbessern und die Anforderungen 2.2.1, 2.2.2 und 2.2.2 überprüfen. Öffnen Sie die Testdatei graph_unit_tests
.
open("graph_unit_tests.m");
Diese Funktionen überprüfen die drei Fehlercodes. Kopieren Sie den Code in Zeile 4 in den Abschnitt der Testmethoden der Datei graph_unit_tests
und speichern Sie die Datei anschließend.
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
Führen Sie die Tests mit Abdeckung erneut aus und öffnen Sie den Abdeckungsbericht.
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
Die Tests decken nun die Fehlercode-Anweisungen ab.
Allerdings gibt es in Zeile 97 eine Anweisung, die von den Tests nicht abgedeckt wird. Die Bedingungen, die erfordern, dass die Tests die Anweisung in Zeile 97 abdecken, führen auch dazu, dass die Anweisung return
in Zeile 87 ausgeführt wird, was bedeutet, dass die Anweisung in Zeile 97 nicht erreichbar ist und tote Logik darstellt.
Beheben von Lücken in der Rückverfolgbarkeit von Anforderungen
Regenerieren Sie die Rückverfolgbarkeitsmatrix, wenden Sie dieselben Filter wie zuvor an und klicken Sie dann in der Symbolleiste auf Highlight Missing Links.
slreq.generateTraceabilityMatrix(mtxOpts)
Top > Link > Missing Links
Top > Type > Functional
Left > Type > Function
Left > Attributes > Test
Erstellen Sie Verknüpfungen zwischen den Fehlercodeanforderungen und den neuen Tests.
Aktualisieren Sie den Verifikationsstatus im Requirements Editor, indem Sie die mit beiden Anforderungssätzen verknüpften Tests erneut ausführen.
status4 = runTests(funcReqs);
Running graph_unit_tests .......... .. Done graph_unit_tests __________
status5 = runTests(testReqs);
Running graph_unit_tests .......... ... Done graph_unit_tests __________
Alle Anforderungen sind mit Tests verknüpft, und alle Tests wurden bestanden.
Nachverfolgen von Anforderungen in generiertem Code
Verwenden Sie Embedded Coder®, um Code aus dem Algorithmus shortest_path
zu generieren, und fügen Sie Anforderungskommentare hinzu, mit denen Sie die Anforderungen im generierten Code nachverfolgen können. Weitere Informationen finden Sie unter Requirements Traceability for Code Generated from MATLAB Code.
Erstellen Sie ein Code-Konfigurationsobjekt, um Code mit einem LIB-Build-Typ zu generieren.
cfg = coder.config("lib","ecoder",true);
Aktivieren Sie den Konfigurationsparameter für den Code, um Anmerkungen zu Anforderungen in den generierten Code aufzunehmen.
cfg.ReqsInCode = true;
Verwenden Sie coder.typeof
(MATLAB Coder), um ein doppeltes Array variabler Größe mit einer maximalen Größe von 100x100 und einen skalaren Doppelwert als Eingaben im generierten Code zu definieren.
mtxType = coder.typeof(ones(100,100),[],1); scalarDblType = coder.typeof(1);
Generieren Sie C Code aus dem Algorithmus shortest_path
mit den angegebenen Code-Konfigurationsparametern und Eingabetypen. Erstellen Sie einen Code-Generierungsbericht und starten Sie den Bericht.
codegen shortest_path -config cfg -args {mtxType, scalarDblType, scalarDblType} -launchreport
Code generation successful: View report
Die Datei shortest_path.c
enthält Kommentare mit einer Zusammenfassung der verknüpften Anforderung, den vollständigen Dateipfad der Datei shortest_path.m
und die verknüpften Codezeilen.
Siehe auch
runTests
| codegen
(MATLAB Coder) | coder.runTest
(MATLAB Coder)