Image
Testautomatisierung in der Automobilindustrie

CI/CD, DevOps & Testautomatisierung in der Automobilindustrie

🕒 Lesedauer: 9 Minuten

Angesichts einer sich rapide wandelnden Technologielandschaft und gestiegener Kundenerwartungen sieht sich die Automobilindustrie mit einer Vielzahl von Herausforderungen konfrontiert. Eine Kernherausforderung ist die effektive Implementierung der Prinzipien kontinuierlicher Integration und kontinuierlicher Bereitstellung (CI/CD) innerhalb einer komplexen Multi-Projekt-Umgebung von mechatronischen Systemen mit Anbindung von Hardware-Software-Integrationstests und unter Anwendung diverser Standards und Normen der Branche.

Wiederverwendbarkeit und Software-Produktlinien

Ein zentraler Aspekt der Automobilindustrie ist die Wiederverwendbarkeit von gemeinsam genutzten Artefakten. Bei klassischen Ingenieurtätigkeiten spricht man häufig von Produktfamilien oder Plattformen. Solche Produktfamilien sind bei der Hardwareherstellung bereits Gang und Gäbe, in der eingebetteten Softwareentwicklung in Form von Software-Produktlinien aber immer noch zu schwach ausgeprägt. Hierbei handelt es sich nicht nur um eine gemeinsame Codebasis, die zwischen zahlreichen Projekten geteilt wird, sondern auch um wiederverwendbare Anforderungen, Architekturen und Tests.

Die Vorteile der Wiederverwendbarkeit sind mannigfaltig: Sie reduziert sowohl die Entwicklungszeit als auch die Kosten und minimiert gleichzeitig die Risiken, die mit der Neuentwicklung verbunden sind. Anforderungen, die in der Konzeptphase festgelegt werden, können in diversen Projekten wiederverwendet und angepasst werden, was die Effizienz des gesamten Entwicklungsprozesses steigert. So können beispielsweise mehrere Projekte gleichzeitig beginnen, nämlich mit der geteilten Basis, ohne dass dafür ein größeres Team benötigt wird. Allerdings führt dies auch zu einer erhöhten Komplexität in der Anforderungsanalyse und -verwaltung. Durch die Verwendung bereits getesteter und validierter Komponenten kann die Qualität des Endprodukts signifikant verbessert werden.

Des Weiteren senkt die Wiederverwendung den Wartungsaufwand für alle beteiligten Artefakte. Ein klassischer Clone-and-Own-Ansatz würde im Laufe der Zeit zu einer zunehmenden Divergenz zwischen den Artefakten verschiedener Projekte führen, da unterschiedliche Teams oft unterschiedliche Implementierungen für ähnliche Anforderungen entwickeln, die dann nicht ineinander übergehen würden. Dies alles ermöglicht es Unternehmen, agiler auf Marktanforderungen zu reagieren und somit einen Wettbewerbsvorteil gegenüber Mitbewerbern zu erzielen, die jedes Projekt von Grund auf neu oder für sich betrachtet entwickeln und testen.

Es ist jedoch wichtig zu unterstreichen, dass nicht alle Elemente zwischen den Projekten geteilt werden können oder sollen. Auf dem stark umkämpften Markt der Automobilindustrie streben viele Kunden nach einzigartigen Features, um sich von der Konkurrenz abzuheben. Diese Notwendigkeit führt oft zu einer Vielzahl von Sonderlösungen, was die Komplexität auf Seiten der Zulieferer beträchtlich erhöht – auch innerhalb der ansonsten wiederverwendeten Artefakte. Dennoch ist die durch Wiederverwendung induzierte Komplexität im Allgemeinen geringer als die, die bei einer Clone-and-Own-Strategie entstehen würde.

Insbesondere die CI/CD-Pipelines (erstellt mit Jenkins , Github Actions oder ähnliche) und deren zugrunde liegende Build-Systeme und Infrastrukturen profitieren von Produktfamilien und sind von kundenspezifischen Wünschen nur sehr gering betroffen. Denn die zu erzeugenden Ergebnisse, wie Binär-Dateien und Reports, oder auch die benötigten Qualitätssicherungswerkzeuge, Standards und Normen sind in der Regel für alle Kundenprojekte einer Familie identisch. Das kann den Entwicklungsaufwand von unterstützenden Tools und Prozessen um ein vielfaches reduzieren.

Integration

Die Wiederverwendung von Code und Tests ermöglicht es, Softwarekomponenten, Testfälle und -szenarien effizient in mehreren Projekten einzusetzen. Dieser Ansatz ist zwar wirtschaftlich attraktiv, birgt jedoch eine Reihe von Herausforderungen. Insbesondere hat jede Modifikation einer geteilten Codekomponente oder eines Testfalls das Potenzial, weitreichende Auswirkungen auf alle Projekte zu haben, die diese Elemente verwenden. Daraus ergibt sich die Notwendigkeit für Entwickler und Integratoren gleichermaßen, ein robustes Abhängigkeitsmanagement zu implementieren oder Änderungen immer in allen möglichen Varianten mit Hilfe automatischer Tests zu prüfen.

Teilweise ist es sehr kompliziert, festzustellen, in welchen Projekten eine Änderung tatsächlich aktiv ist, wodurch es vorkommen kann, dass eine Änderung in allen Projekten getestet werden muss, was zusätzliche Zeit kosten kann. Die Integratoren müssen zusammen mit den Komponentenverantwortlichen und Softwareprojektleitern alle Konfigurationen im Blick behalten und sicherstellen, dass jedes Projekt entsprechend der Anforderungen konfiguriert ist. Denn der Code (Configurable Sources) ist nicht mehr die alleinige Wahrheit.

Erst zusammen mit der Projektkonfiguration (Configured Sources) und der Parametrisierung ergibt sich das Gesamtprodukt. Der Umfang an konfiguriertem Code ist in Software-Produktlinien auf Sicht eines einzelnen Projekts größer als in Clone-and-Own, auf Sicht der gesamten Produktlinie jedoch kleiner. Tools wie FeatureIDE oder Kconfig können in Verbindung mit Build-Tools (wie Make - GNU Project - Free Software Foundation oder CMake ) oder Präprozessor-Direktiven helfen, den Code konfigurierbar zu gestalten. Solche Entwicklungswerkzeuge sind in der Regel auf einen Einsatz in CI/CD-Umgebungen ausgelegt und lassen sich problemlos automatisieren.

Pipeline Automatisierung

Flächendeckende Automatisierung ist wichtig, nicht nur bei den Builds, sondern auch beim Testen. Aber jede Automatisierung bringt wenig, wenn sie ewig dauert. Wir schaffen eine weitere Ebene der Komplexität aus der Notwendigkeit heraus, dass Builds und Tests in angemessener Zeit abgeschlossen werden müssen - "Fail Fast" ist die Devise.

Alleine das Kompilieren und Linken kann aufgrund der vielen Optimierungsschritte im Embedded-Bereich bereits über eine Stunde dauern. Die Hardware wird mit minimalen Ressourcen (RAM, ROM, Laufzeit) entworfen, denn sie wird in extrem hohen Stückzahlen verkauft und soll möglichst viel Gewinn erwirtschaften. Die Software hingegen wird einmal entwickelt und auf beliebig vielen Steuergeräten vertrieben und muss genau auf diese Ressourcen-Einschränkungen hin optimiert und selbstverständlich auch (automatisch) getestet werden. Nicht-funktionale Tests u.a. für Ressourcenverbrauch sind essentiell und können kontinuierlich überprüfen, ob die Hardware und Software in einer möglichst günstigen Kombination noch zusammenpassen. Umfangreiche Builds und komplette Testdurchläufe (funktional und nicht-funktional) können hier trotz Automatisierung leicht 24h dauern.

Mögliche automatisierbare Tests sind:

  • Statische Analysen (Coding-Regeln, Best-Practices)
  • Dynamische Analysen wie Wertebereichsüberprüfung zum Ausschließen von Division durch 0 (u. a.)
  • Unit-Tests
  • Tests für Ressourcenverbrauch (RAM, ROM, Laufzeit)
  • Software-Integrations-Tests (Software-Software-Integration für die Überprüfung von Signalketten)
  • Software-Systemtest (Simulationen auf dem Entwickler-PC, simulierte Anschalttests und vollständige Simulation von Fahrmanövern)
  • Software-Hardware-Integrations-Tests (Die Software im Verbund mit der Hardware testen)

Im Falle statischer Code-Analysen, also unter anderem das Prüfen auf MISRA C-Regeln (Motor Industry Software Reliability Association) oder HIS-Metriken (Herstellerinitiative Software, einige Beispiele für Metriken gibt es hier: HIS Source Code Metrics - Emenda), können vollständige Testläufe wegen der Konfigurierbarkeit sogar noch mehr Zeit beanspruchen. Dadurch haben sich in einigen Firmen die sogenannten täglichen Nightly-Builds, also eine nächtliche Überprüfungen verschiedener Qualitätsstufen nach der Integration, etabliert und lange gehalten. Eine tatsächliche kontinuierliche Integration ist vielfach sehr schwer, aber notwendig.

Deswegen ist es unumgänglich, dass mehrere Prozesse parallel laufen müssen und, dass Prozesse wo immer möglich inkrementell arbeiten, um die Agilität des Entwicklungszyklus aufrechtzuerhalten. Inkrementell bedeutet in diesem Zusammenhang auch, dass langwierige Prozesse gar nicht erst gestartet werden sollten, wenn durch frühere, schnellere Tests bereits absehbar ist, dass sie keinen Erfolg haben werden oder keinen neuen Beitrag leisten. Im Falle von neuen Änderungen, können, wenn möglich, auch nur die Änderungen getestet und betroffene Tests durchgeführt werden, um Zeit zu sparen. Für Freigaben können dann wiederum automatisierte Regressionstests auf der gesamten Code-Basis durchgeführt werden. Für solche Fälle sind mehrstufige CI/CD-Pipelines wichtig und beispielhaft in der Grafik dargestellt:

 

Image
mehrstufige-ci-cd-pipeline-in-automobilindustrie.png

Bild 1: Mehrstufige CI/CD-Pipeline in der Automobilindustrie

 

Mehr Geschwindigkeit ist dann irgendwann nur noch durch mehr Rechenpower möglich, die wiederum mehr Geld kostet. Ich kenne bereits interne Rechenzentren, die mehrere Hunderttausend bis zu Millionen Euro Investment gekostet haben, nur um ein einziges Steuergerät zu entwickeln. Hunderte Jenkins Agents mit jeweils 48 CPU-Kernen, 100GB RAM und den den schnellsten Speichern, die 24/7 damit beschäftigt sind, kontinuierlich die Qualität neuer Änderungen zu bewerten und deren Integration automatisch voranzutreiben.

Dazu ein mehrköpfiges Team was sich um die Infrastruktur kümmert, ein Team für IT-Belange und ein weiteres Team für die eigentlichen CI/CD-Pipelines und die Tool-Automatisierung. Und alles kostet Geld. Dasselbe Setup, skalierbar mit Kubernetes und Docker, in der Cloud abzubilden, ist mit vielen Security-Bedenken behaftet, benötigt komplexere Architekturen und unterliegt Leistungsschwankungen der Cloud-Provider und ist deswegen in der Automobilbranche wenig verbreitet. Die Dauerlast und das zusätzliche Know-how machen diese Lösung oft sogar noch teurer.

Shift-Left Testing

Das klingt zunächst wie ein Dilemma oder gar ein Paradoxon. Denn eigentlich sollte CI/CD Geld einsparen und nicht mehr Geld kosten. Aber das Geld wird von Beginn an in die Softwarequalität gesteckt und soll dazu führen, Fehler frühzeitig im Entwicklungszyklus zu erkennen (shift-left). Denn Fehler, die ich später finde, werden in der Regel noch teurer als die initialen Kosten. Denn sollte ein Fahrzeug erst einmal auf der Straße sein, und ein Rückruf aufgrund eines Softwarefehlers notwendig sein, entstehen dadurch nicht nur enorme Werkstattkosten. Zusätzlich kann dadurch der Ruf des Herstellers oder Zulieferers nachhaltig geschädigt werden, was weitere Geschäftsbeziehungen zwischen Herstellern und Zulieferern und auch Endkunden dauerhaft beenden kann. Solche Auswirkungen sind in der Regel um ein vielfaches kostspieliger.

Integrations- und Systemtests

Eine große Verantwortung, Fehler tatsächlich früh zu finden, kommt hier den DevOps-Teams zu, also allen Teams, die kollaborativ auch an Infrastruktur, IT und CI/CD arbeiten, und die eigentliche Produktentwicklung unterstützen. Ein Fehler eines der Teams kann die Entwicklung der Steuergerätesoftware komplett zum Erliegen bringen. Dies führt sowohl zu Problemen mit der CI/CD-Hardware, virtuellen Maschinen oder Netzwerk, als auch zu Rechte-Problemen oder Fehlern in der Ausführung von Pipelines.

Eine Freigabe zu behindern und im schlimmsten Fall ein Fließband lahmzulegen, ist ein wesentliches wirtschaftliches Risiko. Ein gutes Zusammenspiel und insbesondere ein intensives Monitoring sind kritisch für den Erfolg. Wenn die Umgebung nicht stabil ist, und das ist sie durch Anbindung von Hardware-in-the-Loop (HIL) und anderen externen Abhängigkeiten nur sehr selten, dann sollten Fehler im Sinne der Resilienz wenigstens früh erkennbar und schnell behebbar sein. Tools wie Kibana und Grafana haben sich hier in der Praxis als Monitoring-Werkzeuge bewährt.

Nachvollziehbarkeit von Tests

Besonders hervorheben möchte ich aus meiner Erfahrung auch den Bedarf, die CI/CD-Pipeline lokal ausführen zu können. Natürlich wollen wir uns alle immer darauf verlassen, dass alle Systeme einwandfrei funktionieren, aber die Realität zeigt uns allzu oft, dass das nicht möglich ist. Ein Entwickler sollte also in der Lage sein, möglichst viele Schritte auch ohne Anbindung an CI/CD lokal durchzuführen. Grundlegend bedeutet dass, in die Pipelines so wenig Logik wie möglich zu packen. Denn Jenkins Pipelines oder Github Actions sind nicht lokal ausführbar. Im besten Fall übernimmt das Build-System (GNU Make oder CMake oder ähnliche) alle Schritte und ich starte und debugge sie lokal. Weniger Pipeline-Code führt hier zu mehr Glückseligkeit. Insbesondere, aber nicht ausschließlich, das Debuggen der Software auf der Zielhardware muss bei der Entwicklung von eingebetteten System immer möglich bleiben.

Auch die Simulationen (Software-in-the-Loop / SIL) und Hardware-in-the-Loop (HIL) müssen für Entwickler weiterhin erreichbar bleiben und sollten nicht exklusiv für CI/CD verwendet werden. Sollten hierbei unterschiedliche HIL-Systeme, beispielsweise trockene und nasse HILs bei Bremsensteuergeräten oder Niedervolt- und Hochvolt-HILs bei Batteriemanagementsystemen Verwendung finden, dann gilt diese Regel selbstredend für alle produktiv verwendeten Konfigurationen. Eine gute Mischung ist hier essenziell.

Jeder muss zu jeder Zeit in der Lage sein, alle Artefakte reproduzierbar zu bauen und zu debuggen. Die große Schwierigkeit ist in der Automobilindustrie nun einmal, dass die überwiegende Mehrheit der Softwarefunktionen immer im Verbund eines mechatronischen Systems, also Hardware + Elektronik + Software, entwickelt und ausgeliefert werden und somit Verbundtests unumgänglich sind. Die Zeit des Zentralcomputers im Auto beginnt zwar bereits, aber bis das flächendeckend etabliert ist, wird es wenig von Hardware losgelöste Software geben. Die Reproduzierbarkeit und das Debugging von CI/CD-Pipelines sind wesentliche Aspekte bei der Implementierung von CI/CD in der Automobilindustrie und dürfen nicht vernachlässigt werden.

Manuelle Tests im Fahrzeug

Als weitere Besonderheit in der Automobilindustrie ist der Fahrversuch zu nennen. Da die CI/CD-Schritte alle Schritte bis zur Auslieferung der Artefakte begleiten sollen, ist es sinnvoll auch den Fahrversuch in den Prozess mit einzubeziehen. Wie bereits erwähnt, wird versucht, so viele Tests wie möglich zu automatisieren. Der Fahrversuch selbst ist nicht automatisierbar, da es hier nicht ausschließlich um das Finden von technischen Fehlern geht, sondern oft auch um das subjektive Empfinden des allgemeinen Fahrgefühls. Hierfür ist der menschliche Fahrer nicht ersetzbar. Der Fahrversuch kann jedoch automatisch angestoßen werden und Ergebnisberichte, Parameteranpassungen oder Fehlerberichte können nach der Testfahrt wieder in das System eingepflegt und Teil der Artefaktsammlung und der freigegebenen Auslieferung werden.

Auch für den Fahrversuch ist ein von den CI/CD-Pipelines unabhängiges Arbeiten notwendig. Stellt der Fahrversuch Unstimmigkeiten fest, muss er in der Lage sein, die Software noch im Fahrzeug durch Parametrierung zu manipulieren und Messergebnisse zu analysieren. Unter Umständen kann es sogar notwendig sein, dass der Fahrversuch die Entwickler für eine Probefahrt oder z.B. für längere Wintererprobungen mitnimmt, um direkt auf der Teststrecke Anpassungen an der Software vornehmen zu können.

Normen und Prozesse

Was wann und wo integriert wird, ist nicht nur abhängig von Funktionalität und Testergebnissen, sondern bedarf zusätzlich besonderer Vorsicht. Spätestens seit dem Diesel-Skandal schauen die Fahrzeughersteller sehr genau darauf, was von den Zulieferern entwickelt, integriert und ausgeliefert wird. Nicht nur muss sichergestellt werden, dass alle Anforderungen erfüllt sind, sondern es muss auch gewährleistet sein, dass nichts integriert wird, was nicht ausdrücklich angefordert wurde. Das bedarf auf Zulieferseite einiges an Vorsicht, wenn die Software als Software-Produktlinie mit vielen Konfigurationen und Parametern entwickelt wird.

Daher wird eine beidseitige Rückverfolgbarkeit (Traceability) nicht nur vom Automotive SPICE Standard vorgeschrieben, sondern wird auch von den meisten Herstellern erwartet, ist teilweise sogar relevant für die Auftragsvergabe. Traceability spielt hier eine entscheidende Rolle, da sie nicht nur die Änderungen im Code nachvollziehbar macht, sondern auch den gesamten Entwicklungsprozess transparenter gestalte. Dies kann jedoch an verschiedenen Stellen eine Herausforderung an die Automatisierungstools stellen, insbesondere wenn es zwischen den verschiedenen Entwicklungsstufen Toolbrüche gibt.

Funktionale Sicherheit

Die Toollandschaft spielt generell eine große Rolle. Open-Source ist aus Gründen der funktionalen Sicherheit (safety) von vielen verpönt, teilweise gibt es gar nicht erst Open Source Lösungen für bestimmte Problemstellungen. Softwaretools müssen aufwändig für den Einsatz im Safety-Umfeld qualifiziert werden, was sich aus Sicht von Open Source Anbietern nicht lohnen dürfte. Eine nachträgliche Einschätzung über Sicherheitsaspekte ist auf Nutzerseite zwar möglich, aber nicht immer sinnvoll.

Zudem gibt es auch funktionale Anforderungen, die aktuell von keiner Open Source Software erfüllt werden. Beispielsweise ist es für Software, die Kriterien für funktionale Sicherheit (safety) erfüllen muss, vorgeschrieben, sie mit Modifizierter Bedingungs-/Entscheidungsüberdeckung, oder Englisch Modified Condition / Decision Coverage (kurz MC/DC) abzudecken. Mir ist kein Open Source Tool bekannt, was das für embedded-C kann. Hingegen unterstützen das Programme wie Cantata und CTC++, die explizit für den Einsatz in der Automobil- und Luftfahrtindustrie entwickelt wurden, von Haus aus.

Zusätzlich zu technischen Standards, spielen auch prozessorientierte Normen eine wichtige Rolle bei der Implementierung von CI/CD in der Automobilindustrie. Beispielsweise legt die ISO 26262 (“Road vehicles - Functional safety”) strenge Anforderungen fest, um die Qualität und (funktionale) Sicherheit der Produkte zu gewährleisten.

Sie definiert unter anderem den Review-Prozess für Softwarekomponenten, der je nach Sicherheitsanforderung variieren kann: zum Beispiel ASIL-D (höchste Stufe der funktionalen Sicherheit) oder QM Komponenten (niedrigste Stufe der funktionalen Sicherheit). Wenn also je nach Komponente entweder ein Walkthrough oder eine Inspection gefordert sind, bzw. eine höhere Anzahl von Reviewern bei sicherheitsrelevanten Aspekten gefordert ist, dann muss während der automatischen Integration auch auf diese Review-Anforderungen geachtet werden und eine richtige Durchführung durch Tools unterstützt oder meistens sogar forciert werden.

AUTomotive Open System ARchitecture (AUTOSAR)

Auch AUTOSAR kann als etablierter Architekturstandard, neben seinen vielen Vorteilen, zu Problemen führen. AUTOSAR ist eine modellbasierte Architektursprache für Automobil-Steuergerätesoftware. Ihr großer Vorteil liegt in der standardisierten Schnittstellenbeschreibung, die eine Interoperabilität und Kompatibilität zwischen verschiedenen Herstellern ermöglicht. Die Schwierigkeit liegt in den Modelldateien. Die Modelldateien sind im XML Format, und damit ist ein gleichzeitiges Arbeiten und Mergen parallel erstellter Änderungen innerhalb dieser Dateien immer mühselig mit modernen Sourcecode-Management-Systemen (SCM) wie Git.

Ohne Verständnis über das unterliegende Modell ist eine parallele Bearbeitung fast unmöglich und muss dementsprechend sequentiell durch Integratoren koordiniert und begleitet werden. Außerdem steht man immer vor der Frage, ob man nur die Modelldateien verwaltet oder auch den generierten Sourcecode. Die generierten Dateien können bei häufigen Generierungen das SCM schnell aufblähen und immer weiter verlangsamen bis ein sogenannter "History Cut" (Abschneiden der Änderungshistorie) notwendig wird.

History Cuts sind schwierig zu handhaben, weil sie die Änderungshistorie in mehrere Blöcke teilen und die Arbeit mit unterschiedlichen Versionsständen erheblich erschweren. Insbesondere in Hinblick auf Rückverfolgbarkeit von Änderungen kann das zusätzliche Hürden in den Weg legen. Aber ein Weglassen des Sourcecodes benötigt weitere Generierungsschritte in den CI/CD-Pipelines, was einen merkbaren Anstieg der Gesamtlaufzeit bewirken kann, und das Projekt dadurch weniger flexibel macht.

Fazit - Balancieren zwischen Effizienz und Qualität

Es ist bei allen erwähnten Schritten, Hürden und Möglichkeiten entscheidend, das richtige Gleichgewicht zwischen Effizienz und Qualität zu finden. CI/CD-Prozesse müssen so konzipiert sein, dass sie sowohl den Anforderungen von Automotive SPICE und ISO 26262 als auch den Anforderungen der verschiedenen Projekte gerecht werden und gleichzeitig die eigentliche mechatronische Produktentwicklung nicht zu stark zeitlich unter Druck setzen. Dies ist eine anspruchsvolle Aufgabe, die eine genaue Kenntnis der spezifischen Anforderungen und Herausforderungen der Automobilindustrie erfordert. Schlussendlich wird die Einführung von CI/CD die Qualität der Software erhöhen und durch schnelles Finden von Fehlern die Effizienz verbessern und somit die Wirtschaftlichkeit steigern.

 

Veröffentlicht am 05.Oktober 2023

Aktualisiert am 17.April 2024

Matthias Eggert

DevOps Engineer

Matthias war viele Jahre in der Automobilbranche als Softwareintegrator, Softwareentwickler und DevOps-Engineer tätig. Dabei ging es immer um sicherheitsrelevante Funktionen wie Bremssysteme oder Batteriemanagementsysteme. Jetzt arbeitet er als DevOps-Engineer bei Qytera und beschäftigt sich sowohl mit modernen Arbeitsweisen, als auch mit aktuellen Technologietrends.

Finden Sie weitere interessante Artikel zum Thema: