Qualitätssicherung für Embedded-Linux-Projekte Unit-Tests mit Open-Source-Werkzeugen

Besser vorhersagbarer Projektverlauf durch Qualitätssicherung

Qualitätssicherung oder „QA“ (Quality Assurance) ist bei Betrachtung heutzutage üblicher Software-Entwicklungsprojekte deutlich unterrepräsentiert. Dies gilt umso mehr für Open- Source-Projekte. Das ist für die Branche aber typisch, wenn man die Projekte auslässt, für die eine enge Einbindung qualitätssichernder Maßnahmen bereits während der Entwicklung zwingend erforderlich ist, z.B. in der Luft- und Raumfahrt, der Medizintechnik oder der Kernkraft.

Dieser Artikel konzentriert sich auf das so genannte „Unit Testing“ als ein wesentliches Element zur Verbesserung von Software-Qualität. Unit-Tests erlauben es dem Programmierer, den Source-Code seines Projekts mit einer Test-Suite zu ergänzen, die weitgehend automatisiert abläuft. Zudem wird die Schwelle, immer und immer wieder Tests an jeder Stelle im Entwicklungsprozess zu wiederholen, deutlich herabgesenkt, und es wird für eine bessere „Vorhersagbarkeit“ des Projektablaufs gesorgt. Anstelle einer schnellen Entwicklung mit hohem Zeitaufwand bei der Fehlerbehebung kann sich der Software-Entwickler nun mehr Zeit für die Definition der Funktionalität nehmen, die dann automatisch von der Source-Code- Ebene bis zu hoher Abstraktionsebene getestet werden kann.

Andere, wichtige Bestandteile eines QA-Konzepts, die eine große Unterstützung bei der Software-Entwicklung liefern können, sind die aus Platzgründen hier nur kurz aufgelisteten Werkzeuge:

  • Bug-Tracking-Systeme (auch bezeichnet als: Request-Tracker, Ticket-System, Issue-Tracker), bekannte Open-Source-Vertreter sind z.B. Request Tracker, Debbugs, OTRS;
  • Memory-Monitore (auch: Memory- Profiler, Leak-Tester), z.B. Valgrind, Electric Fence;
  • Software Code-Checker, z.B. Werkzeuge wie Lint;
  • Compiler-Warnungen, z.B. gcc -Wall -Wextra;
  • Black-Box Test-Frameworks, wie z.B. Dejagnu.

Im Folgenden wird ein Szenario für die Entwicklung eines Embedded-Software- Pakets im GNU-/Open-Source- Stil vorgestellt, das aber auch in einem proprietären Umfeld angewendet werden kann. Die Voraussetzungen hierfür sind:

  • Das Target-System ist schnell genug und verfügt über ausreichend Kapazität, um einen gewissen Overhead für Test-Software zu verarbeiten. Dies gilt auch für den Speicher und die Anbindung (Netzwerk oder irgendwie gearteter Terminal-Zugang, z.B. serielle Verbindung).
  • Die meisten Testfälle für Funktionen (im Beispiel C-Funktionen) können in einer Testumgebung weitgehend automatisiert erzeugt werden (beispielsweise können Input-Sequenzen in irgendeiner Weise getriggert werden).

JUnit – Mutter aller Unit-Test-Suiten

Die üblicherweise im Unit-Test genutzten Tool-Suiten sind abgeleitete Versionen des wohlbekannten Test- Frameworks JUnit von Kent Beck und Erich Gamma, die in den jeweiligen Programmiersprachen entwickelt wurden. Da es relativ simpel ist, dieses Framework trotz seiner Mächtigkeit in einer neuen Sprache zu implementieren, ist es mittlerweile in praktisch jeder Programmiersprache erhältlich und weitgehend akzeptiert. Mitunter gibt es sogar mehrere bekannte Implementierungen für eine einzelne Sprache in Abhängigkeit unterschiedlicher Entwicklungsumgebungen. Bekannte Vertreter sind beispielsweise: JUnit für Java, CUnit und autounit für C, PyUnit/unittest für Python sowie „Test::Unit“ und TAP für Perl.

Diese Aufstellung ist bei Weitem nicht vollständig. Es ist aber leicht, eine Version für die präferierte Sprache zu finden. Im nachfolgend beschriebenen Beispielprogramm werden, wo immer möglich, Standard-Tools der GNU-Welt genutzt. Das schließt die bekannten Frameworks wie die autotools (autoconf, automake, libtool, aclocal, autoheader) mit ein wie auch die Zusatz-Tools wie z.B. GNU autounit, make, gcc. Diese sind allgemein anerkannt und weit verbreitet in der Open-Source-Welt. Der Kasten enthält eine kurze Beschreibung dieser Vertreter.