Das Wissensportal für IT-Professionals. Entdecke die Tiefe und Breite unseres IT-Contents in exklusiven Themenchannels und Magazinmarken.

heise conferences gmbh

(vormals SIGS DATACOM GmbH)

Lindlaustraße 2c, 53842 Troisdorf

Tel: +49 (0)511/5352-100

service-sigs@heise.de

Testautomatisierung in der Automobilindustrie: vom Jenkinstein zur wartbaren Testplattform

Testautomatisierung über alle Teststufen hinweg ist in der Automobilindustrie unverzichtbar. Doch was passiert, wenn die gesamte Testlogik in CI-Pipeline-DSL implementiert wird? Der Artikel ist ein Erfahrungsbericht aus der Entwicklung von Embedded Software. Er zeigt einen praktischen Weg von einem monolithischen „Jenkinstein“ mit Tausenden Zeilen Groovy-Code, der Build-, Test- und Deployment-Logik vermischte, zu einer modularen Testplattform auf Basis von Python und Pytest. Der Schlüssel: Quality Gates als einfache Pytest-Marker-Selektion, die lokal und in CI identisch funktionieren.

Author Image
Karsten Günther

Softwareingenieur und Product Owner

Author Image
Alexandru Maxiniuc

Plattformarchitekt


  • 23.04.2026
  • Lesezeit: 8 Minuten
  • 185 Views

Das Problem: Testlogik am falschen Ort

Unsere CI-Reise begann 2005 in der Automobilzulieferindustrie. Der Ausgangspunkt war ernüchternd: kein einziger Unit-Test im Repository. Getestet wurde explorativ im Target, im Labor oder direkt im Fahrzeug, mit Messtechnik, Debugger und Oszilloskop. Keine Testautomatisierung, nur Nightly Builds mit dem höchsten Qualitätskriterium „Software linkbar”. Wir nannten diesen Zustand „Continuous Kind im Brunnen“: reaktiv statt präventiv.

Die ersten Verbesserungsversuche brachten Unit-Tests auf Basis eines eigenen CUnit-Frameworks und Jenkins als CI-Server. Doch mit weiteren Teststufen wie statischer Codeanalyse, Softwareintegrations- und Systemintegrationstests passierte eine fatale Entwicklung: Für jede Teststufe wurde ein eigener Jenkins-Freestyle-Job erstellt, später wurden diese in immer komplexere Groovy-Pipelines konsolidiert.

Das Ergebnis war unser „Jenkinstein“, ein Monster aus Zehntausenden Zeilen Jenkins-Pipeline-DSL, das als Build-, Test-, Deployment- und Monitoringsystem gleichzeitig fungierte. Die Pipeline enthielt die gesamte Geschäftslogik: welche Varianten gebaut werden, welche Tests für welche Teststufe laufen, wie Ergebnisse aggregiert werden. Die Konsequenzen waren gravierend:

  • Nicht reproduzierbare Testergebnisse: Fehler, die in CI auftraten, konnten lokal nicht nachgestellt werden, weil die Testlogik nur in der Pipeline existierte.
  • Unwartbarer Code: Groovy-DSL-Code in Jenkins ist schwer testbar, schwer zu debuggen und für die meisten Entwickler unverständlich.
  • Hoher Wartungsaufwand: Zwei Scrum-Teams waren zu mindestens 50 Prozent mit der Pflege der Pipelines beschäftigt.
  • Kein Shift Left: Entwickler konnten Quality Gates nicht lokal ausführen und erhielten Feedback erst nach dem Push.

Die Erkenntnis: CI und lokal unterscheiden sich nur in der Orchestrierung

Der Wendepunkt kam mit einer simplen Erkenntnis: CI-Umgebungen und lokale Entwicklermaschinen unterscheiden sich primär in der Orchestrierung, nicht in der eigentlichen Test- und Build-Ausführung. Ein Build, ein Unit-Test, eine statische Analyse – all das sollte mit denselben Kommandos funktionieren, egal ob lokal oder auf einem CI-Agent.

Daraus leiteten wir fünf Architekturprinzipien ab:

  • Separation of Concerns: Die Pipeline orchestriert nur, keine Geschäftslogik in Pipeline-DSL.
  • Local-First Development: Jenkins führt exakt dieselben Kommandos aus, die Entwickler lokal nutzen.
  • Bootstrapping: Build-Skripte lösen alle Abhängigkeiten selbst auf.
  • Unified Build System: CMake als Meta-Build-System für alle Varianten und Artefakte.
  • Quality Gates als Testselektion: Verschiedene Teststufen sind lediglich unterschiedliche Pytest-Marker-Selektionen.

Die Lösung: unsere SPLE-Plattform

Mit diesen Prinzipien im Kopf entwarfen wir eine modulare interne Entwicklerplattform (auch IDP: Internal Developer Platform) für Software Product Line Engineering (SPLE). Unsere SPLE-Plattform verfolgt vier Hauptziele:

  • Shift Left: Tests so früh wie möglich im Entwicklungsprozess, nicht erst im Nightly Build, sondern bereits beim Pull Request.
  • Continuous Integration: Schnelles, zuverlässiges Feedback für Pull Requests und Integrationsbranches.
  • Reuse: Unterstützung mehrerer Kundenprojekte mit gemeinsamen Komponenten und Variantenmanagement, eine Plattform für die gesamte Software-Produktlinie.
  • Automation: Automatisierte Erzeugung aller benötigten Build-Artefakte und Reports.

Das Herzstück der Plattform ist die Nutzung von Pytest als universelles Test-Framework für alle Quality Gates: vom Build über Unit-Tests bis hin zu Integrationstests. Jede Teststufe wird durch einen Pytest-Marker repräsentiert, siehe Listing 1.

class Test_MyVariant:
  variant = "MyVariant"

  @pytest.mark.unittests
  @pytest.mark.gate.develop_pr
  @pytest.mark.gate.develop_push
  @pytest.mark.gate.develop_nightly
  def test_unittests(self):
    spl_build = SplBuild(variant=self.variant,
      build_kit="test", target="unittests")
    exit_code = spl_build.execute()
    assert exit_code == 0, "Unit tests failed"

  @pytest.mark.integrationtests
  @pytest.mark.gate_develop_nightly
  def test_integrationtests(self):
    spl_build = SplBuild(variant=self.variant,
      build_kit="test", target="integrationtests")
    exit_code = spl_build.execute()
    assert exit_code == 0, "Integration tests failed"
Listing 1: Pytest

Die Quality-Gate-Auswahl erfolgt dann durch den Trigger-Typ:

  • Pull Request: pytest -m "gate_develop_pr" – schnelle Tests für schnelles Feedback
  • Develop-Branch: pytest -m "gate_develop_push" – vollständige Testsuite
  • Nightly Build: pytest -m "gate_develop_nightly" – inklusive langläufiger Tests

Damit werden Quality Gates von undurchsichtiger Pipeline-Magie zu transparenten, reproduzierbaren Testselektionen. Ein Entwickler, der einen Fehler im CI nachstellen möchte, führt lokal exakt denselben Pytest-Aufruf aus, kein Pipeline-Debugging, kein „works on my machine“. Unser Demoprojekt SPLed benutzt exakt diesen Ansatz. Jede Variante im Ordner variants definiert in ihrer Testklasse verschiedene Testtypen (Unittests, Integrationstests) und weist diesen entsprechende Quality Gates zu.

Abbildung 1 zeigt unseren Ansatz als Flussdiagramm: Die Pipeline wählt basierend auf dem Trigger-Typ (Pull Request, Branch-Push, Nightly Build) lediglich ein Quality Gate als Menge von Pytest-Markern aus und orchestriert die parallele Testausführung über mehrere Agents.

SPLE-Pipeline mit Quality-Gate-Selektion und paralleler Testausführung

Abb. 1: SPLE-Pipeline mit Quality-Gate-Selektion und paralleler Testausführung

Der Technologie-Stack

Die SPLE-Plattform setzt auf einen bewusst schlanken Stack:

  • Scoop: Der Windows-Paketmanager Scoop für die automatische Installation aller Toolchains – kein manuelles Setup, kein „bei mir fehlt Tool X“.
  • CMake + Ninja: CMake als Meta-Build-System generiert performante Ninja-Build-Dateien für alle Varianten. Ein einheitliches Build-System statt fragmentierter Makefiles.
  • Python + Pytest: Alle Quality Gates sind Pytest-Tests mit Markern. Die Testlogik ist wartbarer Python-Code statt Groovy-DSL.
  • Pypeline: Unser CI-agnostischer Pipeline-Runner ist Pypeline. Pipeline-Schritte werden als Python-Klassen implementiert und in einer YAML-Datei konfiguriert. Dieselbe Pipeline läuft auf dem Entwickler-Laptop, in Jenkins und in GitHub Actions.
  • Jenkins: Nur noch dünne Orchestrierungsschicht. Das Jenkinsfile ist minimal. Es ruft Pytest mit den passenden Markern auf, mehr nicht.

Das Entscheidende ist die konsequente Trennung: Die Pipeline weiß wann und wo Tests laufen (Orchestrierung), aber nicht was und wie getestet wird (Geschäftslogik).

Was wir dabei gelernt haben

Das Law of the Instrument ist real. Wer einen Hammer hat, für den sieht alles wie ein Nagel aus. Jenkins ist ein hervorragendes Orchestrierungswerkzeug, aber kein Build-System und kein Test-Framework. Wir haben Jahre gebraucht, um diese Grenze zu erkennen und konsequent einzuhalten.

Separate Repositories für Pipeline und Produktcode sind ein Anti-Pattern. Wenn die CI-Konfiguration in einem eigenen Repository liegt, entsteht eine künstliche Trennung, die Reproduzierbarkeit unmöglich macht. Pipeline-als-Code gehört ins Produktrepository.

Testautomatisierung muss lokal funktionieren. Der wichtigste Qualitätsindikator einer Testautomatisierung ist die Frage: „Kann ein Entwickler diesen Test auf seiner Maschine ausführen?“ Wenn die Antwort „Nein“ lautet, stimmt die Architektur nicht.

Die Plattform als Produkt behandeln. Der größte organisatorische Hebel war, unsere Testplattform als eigenes Produkt innerhalb eines Agile Release Train (Scaled Agile Framework/SAFe) zu entwickeln. Regelmäßige Sprint Reviews mit echtem Nutzerfeedback, dediziertes Budget von der Geschäftsleitung und ein klarer Produktname schaffen Ownership und Nachhaltigkeit.

Fazit und Ausblick

Die Transformation vom Jenkinstein zur modularen Testplattform hat sich für alle Beteiligten gelohnt. Entwickler erhalten schnelles, lokal reproduzierbares Feedback. Plattform-Ingenieure pflegen wartbaren Python-Code statt Tausender Zeilen Groovy-DSL. Das Management hat transparente Qualitätskriterien und einen stets Release-fähigen Softwarestand.

Der Schlüssel lag nicht in einem neuen Tool, sondern in einer architektonischen Entscheidung: Testlogik gehört nicht in die Pipeline. Pytest-Marker als Abstraktion für Quality Gates sind einfach, transparent und universell – vom Unit-Test bis zum Systemtest, von der Entwicklermaschine bis zum CI-Server.



Quelle Aufmacherbild, ©pixabay.com/de/

. . .

Author Image

Karsten Günther

Softwareingenieur und Product Owner
Zu Inhalten

Karsten Günther ist seit 25 Jahren leidenschaftlicher Softwareingenieur und kann auf Erfahrungen im Bereich der Signalverarbeitung und eingebetteten Echtzeitsysteme, in der Automatisierung von Entwicklungsprozessen sowie in der Entwicklung von Methoden, Werkzeugen und Pipelines für Continuous Integration (CI) zurückgreifen. Er ist als Ingenieur, Tester und Architekt in der Automobilbranche unterwegs und arbeitet zurzeit als Product Owner der SPLE-Plattform im Rhein-Main Team (RMT) der Marquardt GmbH, wo er sich intensiv mit internen Entwicklungsplattformen und Software Product Line Engineering (SPLE) beschäftigt.

Author Image

Alexandru Maxiniuc

Plattformarchitekt
Zu Inhalten

Alexandru Maxiniuc bringt fast 20 Jahre Erfahrung in der Automobilindustrie mit, spezialisiert auf sicherheitskritische eingebettete Software für Bremssysteme. Er begeistert sich für eingebettete Software, Build-Systeme und Software Product Line Engineering. Alexandru hat innovative Lösungen entwickelt, kleine Softwareteams geleitet und die Einführung effizienter Entwicklungspraktiken vorangetrieben. Er entwickelt aktiv Open-Source-Tools und teilt sein Wissen gerne, um Teams bei der Verbesserung ihrer Software-Engineering-Fähigkeiten zu unterstützen – in seiner aktuellen Position als Plattformarchitekt der SPLE-Plattform im Rhein-Main Team (RMT) der Marquardt GmbH. https://maxiniuc.com/


Artikel teilen