Was ist ein Mutationstest? (Beispiel)

โšก Intelligente Zusammenfassung

Beim Mutation Testing werden absichtlich kleine Fehler in den Quellcode eingefรผhrt und anschlieรŸend die bestehende Testsuite gegen jede fehlerhafte Version ausgefรผhrt, um zu messen, ob diese Tests ausreichend sind, um die ร„nderung zu erkennen.

  • ๐Ÿ”˜ Definition: Ein Mutant ist das Programm, das eine absichtliche syntaktische ร„nderung enthรคlt, und seine Tรถtung beweist, dass ein Test diese ร„nderung erkannt hat.
  • โ˜‘๏ธ Verarbeiten: Erzeuge Mutanten, fรผhre die Testsuite gegen das Original und die Mutanten aus, vergleiche die Ergebnisse und verbessere anschlieรŸend die Tests, die Fehler รผbersehen haben.
  • โœ… OperaTore: OperaDie drei Hauptfamilien von Mutanten entstehen durch nd-Ersatz, Expressionsmodifikation und Anweisungsmodifikation.
  • ๐Ÿงช Ergebnis: Der Mutationswert gibt den Prozentsatz der getรถteten Mutanten an und misst die Durchsetzungsstรคrke, nicht nur die Ausfรผhrung der einzelnen Zeilen.
  • ๏ธ Werkzeug: Stryker-Abdeckungen JavaSkript, TypeScript, C# und Scala, wรคhrend PIT JVM-Bytecode innerhalb von Maven und Gradle baut.
  • โš ๏ธ Kosten: Bei jeder Mutante wird die gesamte Testsuite erneut ausgefรผhrt, daher ist das Mutationstesting ohne Automatisierung langsam, teuer und unpraktisch.

Mutationstests

Was ist ein Mutationstest?

Mutationstests Mutationstests sind eine Art Softwaretest, bei dem bestimmte Anweisungen des Quellcodes verรคndert (mutiert) werden, um zu รผberprรผfen, ob die Testfรคlle Fehler im Quellcode finden kรถnnen. Ziel des Mutationstests ist es, die Robustheit der Testfรคlle sicherzustellen, sodass sie bei verรคndertem Quellcode fehlschlagen.

Die in einem mutierten Programm vorgenommene ร„nderung muss extrem gering sein, damit sie das Gesamtziel des Programms nicht beeintrรคchtigt. Mutationstests werden auch als fehlerbasierte Teststrategie bezeichnet, da sie das gezielte Erzeugen eines Fehlers im Programm beinhalten. Es handelt sich um eine Form des Mutationstests. WeiรŸ Box Tests das hauptsรคchlich angewendet wird wรคhrend Unit Tests.

Mutation Testing wurde 1971 in einer studentischen Arbeit von Richard Lipton vorgeschlagen und 1978 in der Arbeit โ€žHints on Test Data Selectionโ€œ von DeMillo, Lipton und Sayward formalisiert. Aufgrund des damaligen Rechenaufwands verlor es an Bedeutung, hat aber seither fรผr Sprachen wie โ€ฆ wieder an Relevanz gewonnen. Java, C#, Python, JavaSkript und XML.

Wie fรผhrt man einen Mutationstest durch?

Im Folgenden sind die Schritte zur Durchfรผhrung eines Mutationstests, auch Mutationsanalyse genannt, aufgefรผhrt:

Schritt 1: Fehler werden in den Quellcode des Programms eingefรผhrt, indem zahlreiche Versionen, sogenannte Mutanten, erstellt werden. Jede Mutante sollte genau einen Fehler enthalten, und das Ziel ist es, die Mutantenversion zum Absturz zu bringen, wodurch die Wirksamkeit der Testfรคlle demonstriert wird.

Schritt 2: Die Testfรคlle werden sowohl auf das Originalprogramm als auch auf das mutierte Programm angewendet. Testfall sollte ausreichend sein und ist darauf ausgelegt, Fehler in einem Programm zu erkennen.

Schritt 3: Vergleichen Sie die Ergebnisse des Originalprogramms und des mutierten Programms.

Schritt 4: Wenn das Originalprogramm und das mutierte Programm unterschiedliche Ausgaben erzeugen, wird das mutierte Programm durch den Testfall beendet. Daher ist der Testfall ausreichend, um die ร„nderung zwischen dem Originalprogramm und dem mutierten Programm zu erkennen.

Schritt 5: Wenn das Originalprogramm und das mutierte Programm die gleiche Ausgabe erzeugen, bleibt die mutierte Version aktiv. In solchen Fรคllen mรผssen effektivere Testfรคlle erstellt werden, die alle mutierten Versionen eliminieren.

Das untenstehende Diagramm tracEs sind immer die gleichen fรผnf Schritte, vom ursprรผnglichen Programm รผber die Erzeugung von Mutanten bis hin zum Urteil, ob man getรถtet wurde oder รผberlebt hat.

Workflow fรผr Mutationstests, der das Originalprogramm, die generierten Mutanten, die Testausfรผhrung und das Ergebnis (getรถtete oder รผberlebende Mutanten) zeigt.

Wie erstellt man Mutantenprogramme?

Eine Mutation ist nichts anderes als eine einzelne syntaktische ร„nderung an einer Programmanweisung. Jedes mutierte Programm sollte sich vom Originalprogramm durch genau eine Mutation unterscheiden.

Ursprรผngliches Programm Mutantenprogramm
Wenn (x>y)
Drucken Sie โ€žHalloโ€œ
Else
Drucken Sie โ€žHalloโ€œ
Wenn (x
Drucken Sie โ€žHalloโ€œ
Else
Drucken Sie โ€žHalloโ€œ

Im obigen Beispielpaar hat sich lediglich der Vergleichsoperator geรคndert. Dennoch wird in einem Testfall, in dem x grรถรŸer als y ist, nun โ€žHiโ€œ anstelle von โ€žHelloโ€œ ausgegeben. Die Abbildung verdeutlicht diese eine syntaktische ร„nderung.

Eine syntaktische ร„nderung an einer Programmanweisung erzeugt einen einzelnen Mutanten.

Was muss in einem Mutantenprogramm geรคndert werden?

Es gibt verschiedene Techniken zur Erzeugung von Mutationsprogrammen. Die drei unten aufgefรผhrten Familien decken die meisten Mutationsoperatoren ab, die in den Tools standardmรครŸig enthalten sind.

Operaund Ersatzbetreiber Ausdrucksmodifikationsoperatoren Operatoren zur ร„nderung von Anweisungen
Ersetzen Sie den Operanden durch einen anderen Operanden (x durch y oder y durch x) oder durch einen konstanten Wert. Einen Operator in einer Programmanweisung ersetzen oder einen neuen Operator einfรผgen. Programmatische Anweisungen werden geรคndert, um mutierte Programme zu erstellen.
Ejemplo:
Wenn(x>y) ersetzen Sie die x- und y-Werte
Wenn(5>y) ersetze x durch die Konstante 5
Ejemplo:
Wenn(x==y)
Wir kรถnnen == durch >= ersetzen und das mutierte Programm wie folgt erhalten:
If(x>=y) und Einfรผgen von ++ in die Anweisung
Wenn(x==++y)
Ejemplo:
Lรถschen Sie den else-Teil in einer if-else-Anweisung
Lรถschen Sie die gesamte if-else-Anweisung, um das Verhalten des Programms zu รผberprรผfen.

Einige Beispiele fรผr Mutationsoperatoren:

  • GOTO-Label-Ersatz
  • Ersatz der Rรผckgabeerklรคrung
  • Lรถschung der Anweisung
  • Einfรผgung unรคrer Operatoren (wie โ€“ und ++)
  • Austausch des logischen Connectors
  • Vergleichbarer Array-Namensersatz
  • Entfernen des else-Teils einer if-else-Anweisung
  • Hinzufรผgen oder Ersetzen von Bedienern
  • Anweisungsersetzung durch ร„nderung der Daten
  • Datenmodifikation fรผr die Variablen
  • ร„nderung von Datentypen im Programm

OperaTors, die eine Randbedingung berรผhren, รผberleben am hรคufigsten, daher weisen Mutationsergebnisse hรคufig auf Lรผcken in zurรผck. Grenzwertanalyse.

Arten von Mutationstests

In Software EngineeringMutationstests lassen sich grundsรคtzlich in drei Typen unterteilen: Anweisungsmutation, Wertmutation und Entscheidungsmutation.

  • Aussagemutation โ€“ Eine Anweisung wird ausgeschnitten, eingefรผgt oder gelรถscht, sodass das Ergebnis die Entfernung einiger Codezeilen sein kann.
  • Wertmutation โ€“ die Werte primรคrer Parameter und Konstanten werden verรคndert, beispielsweise durch die ร„nderung einer Schleifengrenze oder eines Schwellenwerts.
  • Entscheidungsmutation โ€“ Kontrollanweisungen werden geรคndert, zum Beispiel umkehrenping ein relationaler Operator oder die Negation einer Bedingung.

Die Werkzeuge gruppieren ihre Operatoren unter diesen drei Kategorien, sodass die Familie, die eine รผberlebende Mutante erzeugt hat, dem Tester mitteilt, welche Art von Assertion fehlt. Eine รผberlebende Entscheidungsmutante markiert รผblicherweise einen ungetesteten Zweig, der sich mit รผberschneidet. Schleifentest.

Automatisierung von Mutationstests

Mutationstests sind manuell extrem zeitaufwรคndig und kompliziert, daher empfiehlt sich der Einsatz von Automatisierungstools, die zudem Kosten sparen. Ein Mutationstest-Tool kompiliert die Mutanten, plant die Testlรคufe, protokolliert, welche Mutante durch jeden fehlgeschlagenen Test beendet wurde, und gibt das Ergebnis aus.

Liste der verfรผgbaren Werkzeuge:

  • Stryker โ€” ein Open-Source-Mutationstest-Framework mit Editionen fรผr JavaDrehbuch und TypeScript (StrykerJS), C# und .NET (Stryker.NET) sowie Scala (Stryker4s).
  • PIT, auch PITest geschrieben โ€“ ein Mutationstestsystem fรผr Java und die JVM, die kompilierten Bytecode verรคndert und sich in Maven einbindet und Gradle baut neben JUnit.

Beide werden als Build-Schritt ausgefรผhrt, gehรถren also in denselben Ordner. kontinuierliche integration Pipeline wie der Rest der Automatisierungstests Suite.

Mutations-Score

Der Mutationswert ist definiert als der Prozentsatz der getรถteten Mutanten bezogen auf die Gesamtzahl der Mutanten.

Mutationspunktzahl = (getรถtete Mutanten / Gesamtzahl der Mutanten) * 100

Die Formel ist unten in der Form dargestellt, in der sie die meisten Tools ausgeben.

Formel zur Berechnung des Mutationsscores: Anzahl der getรถteten Mutanten geteilt durch die Gesamtzahl der Mutanten und multipliziert mit einhundert

Testfรคlle gelten als mutationsadรคquat, wenn die Punktzahl 100 Prozent erreicht. In der Praxis muss der Nenner bestimmte Werte ausschlieรŸen. รคquivalente Mutanten Mutanten, deren verรคnderte Syntax sich exakt wie das Original verhรคlt, kรถnnen von keinem Test eliminiert werden. Daher melden die Tools die Anzahl der eliminierten Mutanten geteilt durch die Summe der eliminierten und รผberlebenden nicht-รคquivalenten Mutanten und รผberlassen es dem Tester, ร„quivalente zu kennzeichnen.

Experimentelle Ergebnisse haben gezeigt, dass Mutationstests eine effektive Methode sind, um die Eignung von Testfรคllen zu messen. Der Hauptnachteil besteht in den Kosten fรผr die Generierung der Mutanten und die Ausfรผhrung jedes Testfalls gegen jede einzelne Mutante.

Mutationstests vs. Code Abdeckung

Hoch Testabdeckung Das beweist keine aussagekrรคftigen Tests. Zeilen- und Zweigabdeckung protokollieren lediglich, welche Anweisungen ausgefรผhrt wurden, nicht aber, ob anschlieรŸend etwas verifiziert wurde. Daher gilt ein Test, der eine Methode aufruft und nichts รผberprรผft, dennoch als abgedeckt. Mutationstests schlieรŸen diese Lรผcke, da ein Mutant nur dann abbricht, wenn eine Assertion tatsรคchlich fehlschlรคgt.

Aspekt Code Berichterstattung Mutationswert
Was es misst Welche Zeilen oder Zweige wurden die Tests ausgefรผhrt? Welche Fehler wurden durch die Tests aufgedeckt?
Empfindlich gegenรผber Behauptungen Nein โ€“ ein Test ohne Assertions erhรถht trotzdem die Testabdeckung. Ja โ€“ ein Mutant รผberlebt, wenn keine Behauptung fehlschlรคgt.
Kosten eines Laufs Ein instrumentierter Testlauf Ein Testlauf pro รผberlebendem Mutanten, bisher also deutlich langsamer.
Typische Verwendung Ein schneller Check bei jedem Commit Eine eingehendere regelmรครŸige รœberprรผfung kritischer Module
Fehlermodus 100-prozentige Abdeckung ohne wirkliche รœberprรผfung ร„quivalente Mutanten, die niemals getรถtet werden kรถnnen

Die beiden Metriken ergรคnzen sich. Die Codeabdeckung erfasst den Code, der nie ausgefรผhrt wurde; der Mutations-Score erfasst den erreichten Code, der nie รผberprรผft wurde. Beide flieรŸen in dieselbe Datenbank ein. Fehlermanagementprozess, zusammen mit MaรŸnahmen wie Defektdichte.

Vorteile von Mutationstests

Im Folgenden sind die Vorteile von Mutationstests aufgefรผhrt:

  • Es handelt sich um einen leistungsstarken Ansatz, um eine hohe Abdeckung des Quellprogramms zu erreichen.
  • Es testet die Testsuite selbst, was kein anderer kann. Softwaretestverfahren tut es direkt.
  • Mutationstests bieten Softwareentwicklern ein hohes MaรŸ an Fehlererkennung.
  • Die Methode deckt Unklarheiten im Quellcode auf und hat die Fรคhigkeit, Fehler aufzudecken, die bei normalen Programmlรคufen nie gefunden werden.
  • Die รผberlebenden Mutanten sind angreifbar: Jeder von ihnen benennt eine bestimmte Zeile und eine bestimmte ร„nderung, die die Suite nicht bemerkt hat.
  • Von diesen Tests profitieren die Kunden, indem sie ein zuverlรคssigeres und stabileres System erhalten.

Nachteile von Mutationstests

Auf der anderen Seite ergeben sich folgende Nachteile beim Mutationstest:

  • Mutationstests sind extrem kostspielig und zeitaufwรคndig, da eine groรŸe Anzahl von mutierten Programmen generiert und kompiliert werden muss.
  • Da dieser Vorgang zeitaufwรคndig ist, kann man mit Fug und Recht behaupten, dass diese Tests ohne ein Automatisierungstool nicht durchgefรผhrt werden kรถnnen.
  • Jede Mutante wird anhand der gleichen Anzahl von Testfรคllen wie das Originalprogramm geprรผft, daher muss eine groรŸe Anzahl von Mutanten gegen die gesamte Testsuite ausgefรผhrt werden.
  • ร„quivalente Mutanten kรถnnen durch keinen Test abgetรถtet werden, und ihre Trennung von echten รœberlebenden erfordert in der Regel eine manuelle รœberprรผfung.
  • Da die Methode den Quellcode verรคndert, ist sie nicht anwendbar auf Schwarz Box Tests.

Wann sollte man Mutationstests einsetzen?

Das oben beschriebene Kostenprofil bedeutet, dass Mutationstests selten bei jedem Commit รผber die gesamte Codebasis ausgefรผhrt werden. Sie amortisieren sich dort, wo ein unentdeckter Fehler teuer ist und der zu testende Code klein genug ist, um sich schnell zu verรคndern.

  • Sicherheitskritische oder finanzielle Logik โ€” Zahlungsberechnung, Steuervorschriften und Autorisierungsprรผfungen, bei denen eine unabsichtliche falsche Antwort schlimmer ist als ein Systemabsturz.
  • Suiten mit verdรคchtig hoher Abdeckung โ€” wenn die Abdeckung nahezu 100 Prozent betrรคgt, aber dennoch Fehler auftreten.
  • Legacy-Code wird refaktoriert โ€” Die Ergebnisse der Mutationsanalyse zeigen, ob die bestehenden Tests eine Regression aufdecken wรผrden.
  • Bibliotheken und gemeinsam genutzte Komponenten โ€” ein Fehler in einem wiederverwendeten Komponente multipliziert sich mit jedem Anrufer.
  • Teams รผben Testgetriebene Entwicklung โ€” Die Punktzahl รผberprรผft, ob die zuerst geschriebenen Tests tatsรคchlich funktionieren.

Es lohnt sich in der Regel nicht, auf Wegwerfprototypen, auf dรผnnem Code oder generiertem Code ohne Verzweigungslogik oder auf Testsuiten, die von langsamen Prozessen dominiert werden, zu arbeiten. Integrationstests Das dauert schon Stunden fรผr einen einzigen Durchlauf.

Die meisten Teams beschrรคnken den Testlauf daher auf geรคnderte Dateien, legen einen Schwellenwert fรผr die relevanten Module fest und รผberlassen den weiteren Testlauf dem grรถรŸeren System. Regressionstests Die Suite trรคgt den Rest der Lebenszyklus von Softwaretests.

Hรคufig gestellte Fragen

Eine รคquivalente Mutante ist eine ร„nderung, die die Syntax, aber nicht das Verhalten verรคndert, beispielsweise das Ersetzen einer Schleifengrenze, die nie erreicht wird. Kein Test kann sie aufheben, daher muss sie gekennzeichnet und ausgeschlossen werden, bevor dem Ergebnis vertraut wird.

Es gibt keine allgemeingรผltige Zahl. Teams setzen รผblicherweise einen hohen Schwellenwert fรผr kritische Module wie Zahlungs- oder Sicherheitslogik und einen niedrigeren fรผr andere Bereiche. Die Verfolgung eines Prozentsatzes ist weniger sinnvoll als die รœberprรผfung jeder einzelnen verbleibenden Mutation in risikoreichem Code.

Das Verfahren basiert auf diesen beiden Annahmen. Die erste besagt, dass Programmierer nahezu korrekten Code schreiben, sodass tatsรคchliche Fehler gering sind. Die zweite besagt, dass Tests, die kleine Fehler aufdecken, auch die daraus resultierenden komplexen Fehler erkennen.

Mutationen auf Dateien beschrรคnken, die im aktuellen Branch geรคndert wurden; Abdeckungsdaten wiederverwenden, sodass nur Tests ausgefรผhrt werden, die eine Mutante betreffen; Mutanten parallel ausfรผhren; den Build bei einem Abfall der Punktzahl anstatt bei einem absoluten Wert fehlschlagen lassen.

Maschinelle Lernmodelle sagen voraus, welche Mutanten wahrscheinlich รผberleben werden, damit der Lauf gekรผrzt werden kann, klassifizieren wahrscheinlich gleichwertige Mutanten zur รœberprรผfung und erzeugen Mutanten, die eher Fehlern in der Projekthistorie รคhneln als einheitlichen Bedienerwechseln.

Ja, was den mechanischen Teil betrifft. Ausgehend von einer รผberlebenden Mutante und der zu testenden Methode erstellt Copilot die fehlende Assertion oder den Grenzfalltest. Ein Reviewer muss jedoch noch bestรคtigen, dass der erwartete Wert korrekt ist und nicht einfach vom aktuellen Verhalten รผbernommen wurde.

Es prรผft das Ergebnis. Testgetriebene Entwicklung erzeugt Tests vor dem Code, aber nichts garantiert, dass diese Tests ausreichend prรผfen. Ein periodischer Mutationslauf an denselben Modulen zeigt, ob der Rot-Grรผn-Zyklus Tests erzeugt hat, die tatsรคchlich bei einem falschen Ergebnis fehlschlagen.

Nein. Fehlerinjektion beschรคdigt die Laufzeitumgebung und Fuzz-Tests Beim Mutationstest werden fehlerhafte Eingaben verarbeitet, wodurch die Anwendung bewertet wird. Der Mutationstest รคndert den Quellcode und bewertet die Testsuite, sodass sich das zu bewertende Objekt รคndert.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: