Mutation Testing und Continuous Integration

Die Clean Code Developer Initiative benennt neben Prinzipien auch diverse Praktiken, die ein Team anwenden sollte. Dazu gehören

Diese vier Praktiken leisten gemeinsam einen sehr wichtigen Beitrag zum Wert der Korrektheit. Die Praktiken Integrations- und Unit Tests sorgen für automatisierte Tests. Die Coverage Analyse stellt sicher, dass die Testabdeckung ausreichend hoch ist. Schlussendlich sorgt der Continuous Integration Prozess dafür, dass Tests und Coverage Analyse vollautomatisiert über den gesamten Code des Projekts ausgeführt werden. Im folgenden wird anhand eines kleinen Beispielprojekts in C# gezeigt, wie Coverage Analyse und Continuous Integration ganz konkret eingerichtet werden können. Dabei kommen Stryker Mutator und GitLab als Tools zum Einsatz. 

Mutation Testing zur Coverage Analyse

Über Stryker Mutator als Tool zur Coverage Analyse habe ich bereits in der dotnetpro einen Artikel veröffentlicht (siehe https://www.dotnetpro.de/tools/testing/mutanten-kommen-killt-2402511.html). Die Idee dahinter ist simpel:

  • Ändere den Code an einer Stelle (bspw. „>“ zu „>=“ oder „+“ zu „-„)
  • Lasse alle Tests laufen
  • Wenn kein Test auf rot geht, ist eine Lücke in der Testabdeckung gefunden

Stryker Mutator steht für JavaScript, C# und Scala zur Verfügung. Für andere Sprachen lassen sich ebenfalls passende Tools finden.

Continuous Integration

Stryker Mutator zur Coverage Analyse

Den vierten Baustein, Continuous Integration, habe ich exemplarisch mit GitLab umgesetzt. Ich habe dort ein Beispielprojekt in C# abgelegt und anschließend den CI Prozess konfiguriert. Im Prinzip ist der Vorgang simpel: Man legt im Wurzelverzeichnis des GitLab Projektes die Datei .gitlab-ci.yml an. Diese ist verantwortlich für die Konfiguration der CI Pipeline. Im Detail wird es dann allerdings an manchen Stellen etwas zeitaufwendig, alle Details zusammenzusammeln und so lange anzupassen, bis alles wie gewünscht läuft. Wichtig dabei ist, dass man die Befehle immer zuerst lokal auf dem eigenen Rechner ausführt. Solange der Befehl lokal nicht funktioniert, sollte man ihn nicht im CI eintragen. Dort wartet man länger auf das Resultat, so dass man lokal schneller vorankommt.

Der CI Prozess läuft in GitLab in Docker Containern. Man kann entweder die GitLab eigene Infrastruktur nutzen und erhält im kostenfreien Plan bereits 400 Minuten CI/CD Zeit zur Verfügung gestellt. Mit sehr wenig Aufwand lässt sich ein Runner zur Ausführung der CI Pipeline auch auf einer eigenen Maschine installieren. Natürlich kann dazu ein Cloud Server verwendet werden. Ich habe es mit einem IONOS Cloud Server in Minuten zum Laufen gebracht. Eine Anleitung für Ubuntu findet sich bspw. hier: https://lindevs.com/install-gitlab-runner-on-ubuntu/

Clean Code Trainings

Geschlossene Firmenkurse

Wir führen alle Seminare als geschlossene Firmenkurse für Sie durch.

Bei Interesse oder Fragen kontaktieren Sie uns gerne.

dotnet-stryker ausführen

Mein Beispielprojekt soll in der Testphase den Befehl dotnet-stryker ausführen. Da das Tool nicht zum Standardumfang des Docker Image dotnet/sdk gehört, muss es zunächst installiert werden. Im Anschluss muss noch der Pfad exportiert werden, damit das Programm gefunden wird. Das folgende Listing zeigt die vollständige CI Konfiguration des Beispiels. Nach Veröffentlichung dieses Beitrags werde ich sicherlich daran weiter basteln.

				
					image: mcr.microsoft.com/dotnet/sdk:latest
stages:
    - build
    - test

build:
    stage: build
    script:
        - dotnet --version
        - dotnet build

test:
    stage: test
    script:
        - dotnet tool install -g dotnet-stryker
        - export PATH="$PATH:/root/.dotnet/tools"
        - cd mutation.tests
        - dotnet-stryker --break-at 95
    artifacts:
        paths: [mutation.tests/StrykerOutput]
        untracked: false
        expire_in: 2 days

				
			

Das gesamte Projekt steht bei GitLab in einem öffentlichen Repository bereit:

https://gitlab.com/slieser/mutation-testing-ci

Zeile 1 definiert, welches Docker Image für die Stages verwendet werden soll. In diesem Fall handelt es sich um das offizielle .NET Core 6.0 SDK Image (mit „latest“ wird aktuell 6.0.3 gezogen). Das SDK ist erforderlich, damit Compiler und Buildsystem zur Verfügung stehen.

Die folgenden Zeilen 2-4 definieren die beiden Stages „build“ und „test“. Ferner wird damit auch die Reihenfolge der Ausführung festgelegt. Es folgen dann die Definitionen der Stages.

In der Stage „build“ wird erst angezeigt, welche .NET Version zum Einsatz kommt (Zeile 9). Dies könnte später bei der Fehlersuche hilfreich sein. Anschließend wird der Befehl „dotnet build“ ausgeführt, um das Projekt zu übersetzen. Letztlich wird so lediglich sichergestellt, dass die Tests erst ausgeführt werden, wenn das Projekt gebaut werden kann. In realen CI Pipelines würden hier Artefakte erstellt und abgelegt, bspw. NuGet Pakete oder Docker Images.

Die „test“ Stage ab Zeile 12 installiert zunächst dotnet-stryker als Tool. Damit der Befehl später gefunden wird, wird der Pfad mit export angehängt (Zeile16). Danach wechselt der Befehl „cd“ in das Verzeichnis, in dem das Testprojekt liegt. Dort wird dann schlussendlich dotnet-stryker ausgeführt. Der Parameter „–break-at 95“ erzwingt, dass der Buildschritt fehlschlägt, wenn weniger als 95% der Mutationen überleben.

Zuletzt wird der Report, den dotnet-stryker erstellt, als Artefakt abgelegt, so dass er bei Bedarf heruntergeladen werden kann. Dieser Schritt kann sicher noch eleganter konfiguriert werden, damit der Report, eine HTML Datei, direkt in GitLab eingesehen werden kann.

Fazit

Die Kombination aus automatisierten Tests, Coverage Analyse und CI ist ein mächtiges Werkzeug, um die Korrektheit sicherzustellen. Es fehlt aktuell noch eine Konfiguration, um auch die TestContainers im GitLab CI Prozess einzubinden. Wir bleiben dran…

Unsere Seminare

course
Clean Code Developer Basics

Prinzipien und Tests – Das Seminar wendet sich an Softwareentwickler, die gerade beginnen, sich mit dem Thema Softwarequalität auseinanderzusetzen. Es werden die wichtigsten Prinzipien und Praktiken der Clean Code Developer Initiative vermittelt.

zum Seminar »
course
Clean Code Developer Advanced

Mit Flow Design von den Anforderungen zum Clean Code – Lernen Sie mit Flow Design einen Softwareentwicklungsprozess kennen, der Sie flüssig von den Anforderungen zum Clean Code führt.

zum Seminar »
course
Clean Code Developer Trainer

Seminare als Trainer durchführen – Dieses Seminar wendet sich an Softwareentwickler, die ihr Wissen über die Clean Code Developer Prinzipien und Praktiken bzw. über Flow Design als Trainer an andere weitergeben möchten.

zum Seminar »

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

de_DEGerman