1 Bewertungen

Code Coverage bei Embedded-Geräten Acht Tipps für das richtige Maß beim Testen

Mit diesen acht Tipps bewältigen Sie die Messung der Codeabdeckung problemlos.

02.10.2019

Die Messung der Code Coverage ist bei Embedded-Systemen zunehmend wichtig, erfordert aber etwas Erfahrung. Denn es gibt gerade bei kleinen Targets ein paar Hürden, die zu überwinden sind. Mit den richtigen Ansätzen und geeigneten Werkzeugen ist die Messung der Testabdeckung jedoch ohne übermäßige Aufwände möglich. Acht Tipps aus der Praxis helfen beim Start.

Die Messung der Testabdeckung, auch als Code Coverage bezeichnet, wird auch bei Embedded-Systemen immer wichtiger. Denn gerade diese Devices sind in vielen Fällen sicherheits- oder geschäftskritisch. Geschäftsprozesse basieren auf IoT-Geräten, Patienten verlassen sich auf intelligente Insulinpumpen, die Avionik in der Luftfahrt ist ohne Embedded-Systeme längst nicht mehr denkbar. Diese Liste ließe sich fast endlos fortsetzen. Mit der Kritikalität der verschiedenen Devices steigen die Anforderungen, die an Sicherheit, Zuverlässigkeit und Funktionalität gestellt werden müssen.

Viele Normen tragen dem Rechnung und fordern explizit die Erfassung der Testabdeckung im Rahmen der Produktverifizierung. Besonders Einsteigern erscheint die Messung der Code Coverage extrem komplex und aufwendig. Beachtet man jedoch einige grundlegenden Aspekte, lichtet sich der Dschungel schnell. Denn Code Coverage ist nicht gleich Code Coverage.

Welche Ansätze am besten zum Tragen kommen, hängt stets vom konkreten, individuellen Projekt ab. Sind diese Rahmenbedingen erst einmal formuliert, wird auch die Messung der Testüberdeckung überschau- und handhabbar.

1. Erwartungen klarstellen

Oft ist den Unternehmen nicht ganz klar, was sie von der Code Coverage zu erwarten haben. Klar muss sein, dass die Code Coverage nicht dazu dient, den Code zu verbessern. Ihr Zweck ist es, zu ermitteln, ob der Code komplett getestet wurde und ob die Testfälle vollständig waren. Damit dient die Code Coverage eher der Verbesserung des Testings – und nicht zuletzt natürlich des Nachweises über die erfolgten Tests.

2. Testtiefe bestimmen

Es gibt zahlreiche unterschiedliche Testabdeckungsstufen. Als Daumenregel gilt dabei: Je aussagekräftiger eine Testabdeckungsstufe ist, desto größer ist der Aufwand, diese zu erreichen. Und damit steigen natürlich auch die entstehenden Kosten.

Leider machen nur wenige Normen, wie etwa DO-178C in der Luftfahrt oder ISO 26262 in der Automobilbranche, konkrete Vorgaben, welche Code-Coverage-Stufe wann benötigt wird. Deswegen ist es wichtig, bereits im Vorfeld des Testings festzulegen, welcher Code nach welchen Kriterien getestet werden soll. Dabei ist es unter Umständen sinnvoll, sich an den oben genannten Normen zu orientieren und den Testumfang an der Kritikalität des Systems auszurichten.

3. Testumfang festlegen

Eine vollständige Code Coverage bedeutet zunächst, dass 100 Prozent der vorgegebenen Teststufe erreicht wurden. Das ist jedoch meist nur im sicherheitskritischen Bereich notwendig. Oft reicht die Information, dass ein Code-Bereich nicht von den Tests erreicht wurde, um einen Fehler zu erkennen.

Zudem sollte man nicht unreflektiert der 100-Prozent-Quote nachrennen. Denn dabei entstehen oft redundante Tests, die bereits getesteten Codes nochmals durchlaufen und so zu mehr Aufwand führen – aber nicht zu neuen Erkenntnissen. Vor allem in unkritischen Anwendungsbereichen gilt: Zwischen „zu wenig“ und „vollständig“ liegt die Stufe „ausreichend“.

4. Sprachspezialist oder Generalist

Es gibt zahlreiche Code-Coverage-Analyzer: von kostenlosen Werkzeugen wie etwa das GNU Coverage Testing Tool Gcov, das Bestandteil des GNU Compiler Collection (GCC) ist, bis hin zu umfassenden Lösungen wie Testwell CTC++, die die Unterstützung unterschiedlicher Sprachen bieten. In Unternehmen, in denen unterschiedliche Sprachen zum Einsatz kommen, ist eine übergreifende Lösung zu empfehlen. So können Entwickler und Tester in einer einheitlichen Oberfläche arbeiten und müssen sich nicht mit unterschiedlichen Tools vertraut machen. Zum Sprachumfang sollte auf jeden Fall C, C++ und Java gehören, da diese im Embedded-Bereich am weitesten verbreitet sind.

5. Speicher sparen

Eine Hürde bei der Code Coverage von kleinen Targets ist der verfügbare Speicher, da der Code zur Messung der Testabdeckung zunächst instrumentiert werden muss. Dabei werden Zähler in den Code eingefügt. Zudem muss auf dem zu testenden Target eine Bibliothek implementiert werden, die unter anderem die Datenübertragung an einen Host übernimmt.

Die Zähler werden in der Regel als globale Arrays im Datenspeicher abgelegt. Vor allem bei sehr knapp dimensionierten Targets kann das zu Problemen führen. Wie sich die Instrumentierung konkret auswirkt, muss im Einzelfall am Projekt ermittelt werden.

Abhilfe schafft ein auf Embedded-Devices spezialisierter Code Coverage Analyzer, der so sparsam wie möglich instrumentiert. Reicht das noch nicht, kann die Code Coverage für jeden Abschnitt separat erfasst werden.

Als dritte Methode lassen sich die Zähler verkleinern. Diese sind üblicherweise 32 Bit groß, können aber auch auf 16 oder 8 Bit reduziert werden. Allerdings sollte hierbei bedacht werden, dass kleinere Zähler beim Testing überlaufen können. Reicht die Information, dass ein Code-Bestandteil durchlaufen wurde, können auch 1-Bit-Zähler eingesetzt werden.

6. Ein Auge auf die CPU

Nicht nur der Speicher ist bei vielen Embedded-Devices sparsam kalkuliert, auch der Prozessor hat oft nur geringe Reserven. Die Instrumentierung wirkt sich aber auch auf den Prozessor aus. Hierbei kann es passieren, dass das definierte Timing nicht mehr eingehalten wird; dies kann unter Umständen zu fehlerhaften Programmabläufen führen. Besonders die Bus-Kommunikation ist hierfür anfällig.

Ob durch die leicht höhere Prozessorlast Probleme auftreten, kann leider im Vorfeld nicht zuverlässig prognostiziert werden. Mögliche Effekte zeigen sich erst am konkreten Projekt. Abhilfe schafft hier die Entlastung durch kleinere Zähler oder durch partielle Instrumentierung.

7. Automatisierung

Immer mehr Tests werden automatisiert. Das ist durchaus sinnvoll, denn manuelle Eingriffe stellen immer eine potenzielle Fehlerquelle dar und verursachen zudem signifikante Kosten.

Besonders bei der agilen Entwicklung mit Continuous Integration/Continuous Deployment (CI/CD) ist die Automatisierung des Tests am Build-System gefordert. Das bedingt jedoch, dass der eingesetzte Code Coverage Analyzer sich in die Tool-Chain und das Build-System integrieren lässt. Auch sollte der Analyzer unabhängig vom eingesetzten Compiler arbeiten.

Ausgefeilte Dashboards und Frontends sind hier eher vernachlässigbar. Gerade bei großen Entwicklungsprojekten kann auf automatisierte Tests und die automatische Erfassung der Code Coverage kaum verzichtet werden.

8. Bündelung der Ergebnisse

Code Coverage erzeugt zunächst einmal große Mengen an Daten. Jeder Bereich im Testing – Unit-Tests, Modul-Tests, Funktionstests und dergleichen – liefert eigene Angaben zur Code Coverage. Um ein vollständiges Bild zu erhalten, sollten diese Informationen aggregiert werden. Dabei obliegt es dem Code Coverage Analyzer, diese Informationen sinnvoll und interpretierbar aufzubereiten.

Zudem sind diese Daten wichtig im Rahmen einer eventuell notwendigen Zertifizierung oder bei Audits. Steht für die relevante Zertifizierung ein Qualification-Kit für den Code Coverage Analyzer zur Verfügung, kann einem dies die Arbeit erheblich vereinfachen.

Fazit

Die Messung der Code Coverage ist nicht trivial, aber auch nicht zu komplex. Somit gibt es kaum einen guten Grund, auf dieses Instrument zu verzichten – auch im unkritischen Bereich. Denn die Testabdeckung hilft auf mehreren Ebenen: Zum einen können die Tests und Testverfahren optimiert werden, was in einigen Fällen zu erheblichen Kosten- und Zeitvorteilen führen kann. Zum anderen stellt das Unternehmen sicher, dass die Produkte angemessen getestet wurden und in einer bestimmten Mindestqualität bei den Kunden ankommen.

Denn einen gravierenden Fehler der IT-Industrie sollten die Embedded-Systems-Anbieter nicht wiederholen: Bananen-Software, die beim Kunden reift. Das werden die Käufer von Embedded-Devices nicht akzeptieren. Schon gar nicht, wenn es sich etwa um medizinische Produkte oder ECUs im Automotive-Bereich handelt.

Bildergalerie

  • Die Instrumentierung des Codes erhöht den Ressourcen-Bedarf der Software deutlich.

    Die Instrumentierung des Codes erhöht den Ressourcen-Bedarf der Software deutlich.

    Bild: Verifysoft

Firmen zu diesem Artikel
Verwandte Artikel