Zum Inhalt springen

Suchen...

CI Pipelines

Wer testet, schützt nicht sich selbst, sondern alle. Wie ein Testnetz in der Embedded-Entwicklung funktioniert und warum CMake, Google Test und ein selbstgebauter Automocker der Schlüssel sind.

7 Min. Lesezeit
Cover für CI Pipelines

CI/CD-Pipelines für eingebettete Software schaffen eine fehlertolerante Entwicklungsumgebung, in der Änderungen automatisch getestet werden, bevor sie in die gemeinsame Codebasis fließen. Der Kern: Unit-Tests spannen ein Sicherheitsnetz, das Regressionen sichtbar macht. Ergänzt durch automatische Mock-Generierung, ein einheitliches Build-System und integrierte Dokumentation lässt sich so R-SPICE-konforme Qualität systematisch sichern.

Das Wichtigste in Kürze

  • Unit-Tests sind kein Qualitätsbeweis für den aktuellen Code, sondern ein Sicherheitsnetz für alle künftigen Änderungen: Je mehr Tests vorhanden sind, desto ruhiger kann ein Team seine Software weiterentwickeln.
  • Wer einen Bug behebt, schreibt zuerst einen Test, der diesen Bug reproduziert, und macht das Testnetz damit enger statt nur den Fehler zu flicken.
  • Marquardt setzt auf eine eigene Open-Source-Plattform namens SPLE, die CMake, Google Test, KConfig und den selbst entwickelten Automocker Hammocking zu einer durchgängigen Embedded-C-Entwicklungsumgebung verbindet.
  • Sphinx-basierte Dokumentationsgenerierung ermöglicht es, Requirements, Testspezifikation und Testergebnisse im selben Source-Code-Repository zu halten und daraus R-SPICE-konforme Komponentenreports zu erzeugen.

Warum Embedded-Teams an Software-Qualität scheitern, wenn sie aus der Hardware kommen

Embedded-Software entsteht oft aus dem Bastelmodus, und genau das wird später zum Problem. Wer aus der Hardware-Entwicklung kommt, fängt selten mit einer durchdachten Build-Umgebung an. Er hackt einen ersten Stand zusammen, die LED blinkt, und das ist der Moment der Freude.

Karsten Günther beschreibt diesen Reiz als den Kern des Programmierens: Man baut etwas, und am Ende tut es etwas. Im Embedded-Bereich ist man damit schnell. Solange das Produkt klein bleibt, trägt dieser Modus.

Der Bruch kommt mit der Komplexität. Sobald ein Produkt verkauft wird und mehrere Kunden eigene Anforderungen stellen, reicht das Hacken nicht mehr. Dann braucht es automatisierte Tests, um eine gleichbleibende Qualität zu halten. Diese Hürde trifft viele Firmen mit starkem Hardware-Erbe gleichermaßen.

Bei Marquardt, einem Hersteller von Batteriemanagementsystemen, Touchpanels, LED-Streifen und Bedienelementen, kommt ein Großteil der Softwareentwickler ursprünglich aus der Hardware. Daraus folgt ein Nachholbedarf in der Softwareentwicklung, der sich nicht durch einzelne Tools schließen lässt, sondern durch eine andere Arbeitsweise.

Was CI/CD im Embedded-Kontext wirklich leisten soll

CI/CD ist die Antwort auf Automatisierung und wiederholbares Testen. Wer Regressionstests automatisiert und repetitiv ausführen will, kommt an Continuous Integration nicht vorbei.

Continuous Integration bedeutet, Änderungen mehrmals täglich in eine Mainline einzuspielen und allen zur Verfügung zu stellen. Mehrere Leute arbeiten an einer Code-Basis, jede Änderung getestet, die Qualität bleibt auf gleichem Niveau.

Das eigentliche Ziel liegt tiefer als die Technik. Continuous Integration soll eine fehlertolerante Umgebung schaffen. Wenn jemand einen Fehler macht, soll diese eine Person das Feedback bekommen, nicht die ganze Organisation.

Karsten erzählt von einem frühen Job, in dem ihm gesagt wurde: Das ist dein Code, dafür bist du verantwortlich, aber verändere bloß nichts, du kannst Sachen kaputt machen. Für einen Softwareentwickler ist das ein Widerspruch. Sein Job ist es, Software zu ändern. Wenn Änderung gefährlich ist, fehlt das Sicherheitsnetz.

Plattform-Engineering: Entwickler bauen Produkte, nicht Build-Systeme

Ein Build-System will kein Entwickler bedienen. Entwickler haben Spaß daran, Funktionalität umzusetzen, nicht daran, Werkzeuge zu pflegen. Genau hier setzt Plattform-Engineering an.

Marquardt baut eine einheitliche Plattform, intern SPLE genannt, für Software Product Line Engineering. Die Plattform gibt Entwicklern alles an die Hand, um ihr Produkt zu entwickeln, es konfigurierbar zu machen und Varianten zu bilden.

Variantenbildung ist hier kein Nebenaspekt, sondern das Geschäftsmodell. Marquardt verkauft Produkte an Kunden, die zwischen dem Hersteller und dem Endverbraucher stehen und individuelle Anpassungen wollen. Eine LED im Auto, ein Waschmaschinenknopf, ein Batteriemanagementsystem: jeder Kunde will sein eigenes Customizing.

Die Aufgabe der Plattform ist es, den Entwickler zu befähigen. Er soll seine Software konfigurierbar machen, diese Konfiguration testen und seine Änderungen integrieren können, ohne etwas kaputtzumachen.

Test-Driven Development liefert ein Sicherheitsnetz, kein Beweis

Ein Test beweist nicht, dass dein aktueller Code funktioniert. Diese Umkehrung ist der Kern von Test-Driven Development. Wer eine einfache Aufgabe löst, etwa zwei Zahlen addieren, schreibt funktionierenden Code auch ohne Test.

Der Wert zeigt sich erst bei Erweiterungen. Kommen neue Anforderungen dazu, kennt niemand alle bereits implementierten Features im Detail. Die Wahrscheinlichkeit, beim Ändern etwas Altes zu zerstören, ist real.

Genau hier wirkt das Testnetz. Bestehende Tests spannen ein Sicherheitsnetz auf. Macht der Entwickler bei einer neuen Anforderung einen Fehler, schlägt ein Test fehl, und er sieht sofort, was er kaputtgemacht hat. Je mehr Tests, desto entspannter die Arbeit.

Du schreibst zuerst einen Test, um den Bug zu reproduzieren. Und das ist keine Verschwendung, weil dieser Test dein Testnetz nur enger macht.

— Karsten Günther

Karsten beschreibt das als Geschenk. Auch beim Bugfixing schreibt man zuerst einen Test, der den Bug reproduziert. Dieser Test bleibt und verengt das Netz dauerhaft. Über Jahre wächst eine Komponente so auf tausende Unit-Tests, die bei jeder Änderung laufen und schnell Feedback geben. Bugfrei wird keine Software, aber je enger das Netz, desto geringer die Wahrscheinlichkeit, alte Features unbemerkt zu zerstören.

Die technischen Eckpfeiler einer Embedded-CI-Plattform

Die SPLE-Plattform von Marquardt steht auf mehreren konkreten Werkzeugen, überwiegend Open Source. Sie greifen ineinander, statt nebeneinander zu existieren.

EckpfeilerFunktion
CMakeBuild-System, reif und mächtig, langjährig maintained
Git mit Branch ProtectionTrunk-Based Development, Änderungen müssen durch ein Gate
Google TestTest-Framework auf C++-Basis als Testrunner
Hammockingselbst entwickeltes Python-Package zur automatischen Mockup-Generierung
SphinxDokumentationsgenerator für Reports und Requirements-Tracing

CMake ist das Fundament für die Build-Umgebung. Marquardt hat es so erweitert, dass es Software Product Line Engineering und damit Varianten unterstützt, was CMake von Haus aus nicht mitbringt. Dazu kommen K-Config, etwas PowerShell und Python.

Google Test bringt die volle Mächtigkeit von objektorientiertem C++ in die Tests. Für Entwickler aus der reinen C-Welt ist der Einstieg eine technische Hürde, weil Google Test C++ ist. Wer angekommen ist, kann Dinge tun, die sonst eher aus Java oder Python bekannt sind.

Hammocking: Mocks automatisch generieren statt von Hand schneiden

In der C-Entwicklung fehlt das Mocking, das objektorientierte Test-Frameworks oft mitbringen. Beim Unit-Testing muss man das zu testende Element von seinen externen Schnittstellen freischneiden. Diese Dependencies will man auflösen.

Marquardt hat dafür ein eigenes Tool gebaut: Hammocking, ein Python-Package, das automatisch Mockups generiert. Der Name spielt auf Hammock, die Hängematte, und Mock zusammen. Die Return-Values externer Schnittstellen lassen sich so als Input- oder Output-Vektoren im Unit-Test nutzen.

Hammocking ist Open Source und auf GitHub verfügbar. Marquardt setzt es intern ein, entwickelt es aber öffentlich weiter. Dasselbe gilt für die gesamte SPLE-Plattform, die sich herunterladen und installieren lässt.

Dokumentation gehört zum Code, nicht in ein separates Tool

Reporting und Nachweispflichten lassen sich in dieselbe Plattform integrieren, in der getestet wird. Marquardt nutzt dafür Sphinx, das Dokumentationstool aus der Python-Welt und die Basis vieler Read-the-Docs-Seiten.

Über Sphinx-Extensions deckt die Plattform Requirements-Tracing, Testspec-Generierung und automatische Testreports ab. Die Dokumentation entsteht ASPICE-konform für die Unit Construction, weil die Anwender im Unternehmen Tracing zu Requirements und das Schreiben von Software-Requirements verlangt haben.

Der Vorteil liegt im Ablageort. Die gesamte Dokumentation liegt im Source-Code-Repository, direkt beim Code. Für jede Komponente lässt sich ein Report generieren, der Designspec, Testspezifikation und Testergebnisse zusammenführt.

Die Testspezifikation wird aus den Google-Test-Suites generiert, die Testergebnisse kommen direkt mit dazu. So lässt sich der Weg vom Requirement bis zum Testergebnis ASPICE-konform durchgehen, ohne Brüche zwischen Werkzeugen.

Wohin sich eine Embedded-Plattform entwickeln muss

Die nächste Stufe ist die Verbreitung im eigenen Haus. Ziel ist es, in den kommenden zwei Jahren möglichst viele Projekte, die noch auf alten Technologien aufsetzen, auf die SPLE-Plattform zu heben. Die Akzeptanz der Anwender ist bereits hoch.

Inhaltlich reicht ASPICE über die Unit Construction hinaus. ASPICE beschreibt das gesamte V-Modell, und genau das ist die Richtung: die Plattform soll das V-Modell so weit unterstützen, wie es die Softwareentwicklung braucht.

Konkret heißt das Hardware in the Loop, Software in the Loop, Software-Integrationstest und System-Integrationstest. Die Plattform soll die Grundlage schaffen, damit diese Teststufen möglichst einfach umzusetzen sind. Aus einem Build-System für Unit-Tests wird so schrittweise eine durchgängige Qualitätsumgebung.

Häufig gestellte Fragen

Eine CI Pipeline (Continuous Integration) automatisiert den Prozess der Softwareentwicklung, indem neuer Code regelmäßig in ein gemeinsames Repository integriert wird. Bei jeder Änderungen werden automatisierte Tests durchgeführt, um sicherzustellen, dass der Code funktionsfähig ist. CD (Continuous Delivery) erweitert dies, indem es die Software automatisch in eine Produktionsumgebung überträgt, sobald Tests bestanden wurden. So wird der Software-Lieferprozess beschleunigt und die Qualität verbessert. Beides zusammen ermöglicht schnelle Updates und erhöhte Teamproduktivität.

Die Hauptunterschiede zwischen einer CI Pipeline und einer CD Pipeline liegen im Fokus und Umfang. Eine CI Pipeline konzentriert sich auf die kontinuierliche Integration von Codeänderungen, um sofortige Fehlererkennung und -behebung zu ermöglichen. Sie testet den Code regelmäßig und erstellt Builds. Eine CD Pipeline hingegen zielt darauf ab, diese Builds automatisch in verschiedene Umgebungen zu deployen, wodurch die Bereitstellung von Software durch Automatisierung und Zuverlässigkeit verbessert wird. Während die CI Pipeline die Integrationsphase optimiert, kümmert sich die CD Pipeline um die Auslieferung der Software.

Die Implementierung einer CI Pipeline beschleunigt die Softwareentwicklung erheblich, indem sie automatisierte Tests und Integrationen ermöglicht. Das reduziert Fehler und verbessert die Softwarequalität, da Bugs frühzeitig erkannt werden. Zudem fördert die CI/CD-Pipeline eine schnellere Bereitstellung von Features und Updates, was die Kundenzufriedenheit steigert. Die Transparenz im Entwicklungsprozess erhöht die Zusammenarbeit im Team, während der kontinuierliche Feedback-Kreislauf die Anpassungsfähigkeit an Änderungen unterstützt. Insgesamt führt die CI Pipeline zu effizienteren Abläufen und einer stabileren Software.

Continuous Integration (CI) ist ein automatisierter Prozess, der sicherstellt, dass Entwicklungsänderungen regelmäßig in die Hauptcodebasis integriert werden. In einer CI Pipeline werden Änderungen durch automatisierte Builds und Tests überprüft. Jeder Entwickler fügt seinen Code in kurzen Abständen hinzu, wodurch Fehler frühzeitig erkannt werden. Die Pipeline führt dann Tests aus, um sicherzustellen, dass der Code funktional ist und keine bestehenden Features bricht. Dies ermöglicht eine kontinuierliche Verbesserung und beschleunigt die Softwareentwicklung.

Eine CI Pipeline besteht typischerweise aus den Phasen: Code-Commit, Build, Tests und Deployment. Diese Phasen sind wichtig, um sicherzustellen, dass der Code kontinuierlich integriert, zuverlässig gebaut und automatisiert getestet wird, bevor er in die Produktionsumgebung gelangt. Dadurch werden Fehler frühzeitig erkannt, die Qualität verbessert und die Bereitstellung von Software beschleunigt. Die CI Pipeline fördert eine effiziente Entwicklungsumgebung und ermöglicht ein schnelles Feedback für Entwickler.

Für die Implementierung von CI-Pipelines sind Tools wie Jenkins, GitLab CI, Travis CI und CircleCI besonders geeignet. Diese Tools bieten benutzerfreundliche Oberflächen, Integration mit Versionskontrollsystemen und umfangreiche Plugins zur Unterstützung verschiedener Programmiersprachen. Zudem ermöglichen sie automatisierte Tests und Deployments, was die Effizienz steigert. Für Container-basierte Anwendungen sind Docker und Kubernetes ebenfalls empfehlenswert. Wählen Sie das Tool, das am besten zu Ihren Projektanforderungen passt.

Eine CI-Pipeline verbessert die DevOps-Implementierung, indem sie automatisierte Tests und Integrationen ermöglicht. Dies reduziert Fehler und erhöht die Softwarequalität, da Codeänderungen ständig geprüft werden. Entwickler können schneller Feedback erhalten, was die Zusammenarbeit fördert und die Release-Zyklen verkürzt. Zudem ermöglicht die CI-Pipeline eine konsistente Umgebung, was das Deployment vereinfacht und beschleunigt. Dadurch wird die Effizienz des gesamten Entwicklungsteams gesteigert und die Time-to-Market verkürzt.

Diese Seite teilen

Ähnliche Beiträge