Wir haben eine große plattformübergreifende Anwendung, die in C geschrieben ist (mit einer kleinen, aber wachsenden Menge an C ++). Sie hat sich im Laufe der Jahre mit vielen Funktionen weiterentwickelt, die Sie von einer großen C / C ++ - Anwendung erwarten würden:
#ifdef
Hölle- Große Dateien, die es schwierig machen, testbaren Code zu isolieren
- Funktionen, die zu komplex sind, um leicht getestet werden zu können
Da dieser Code für eingebettete Geräte bestimmt ist, ist es sehr aufwändig, ihn auf dem eigentlichen Ziel auszuführen. Daher möchten wir mehr von unserer Entwicklung und unseren Tests in schnellen Zyklen auf einem lokalen System durchführen. Wir möchten jedoch die klassische Strategie "Kopieren / Einfügen in eine C-Datei auf Ihrem System, Beheben von Fehlern, Kopieren / Einfügen zurück" vermeiden. Wenn Entwickler sich die Mühe machen, dies zu tun, möchten wir in der Lage sein, dieselben Tests später neu zu erstellen und automatisiert auszuführen.
Hier ist unser Problem: Um den Code modularer zu gestalten, muss er testbarer sein. Um jedoch automatisierte Komponententests einzuführen, müssen diese modularer sein.
Ein Problem ist, dass wir, da unsere Dateien so groß sind, möglicherweise eine Funktion in einer Datei haben, die eine Funktion in derselben Datei aufruft , die wir für einen guten Komponententest stubben müssen. Es scheint, dass dies weniger problematisch wäre, da unser Code modularer wird, aber das ist noch weit entfernt.
Eine Sache, über die wir nachgedacht haben, war das Markieren des Quellcodes "bekanntermaßen testbar" mit Kommentaren. Dann könnten wir ein Skript-Scan-Quelldateien für testbaren Code schreiben, es in einer separaten Datei kompilieren und es mit den Unit-Tests verknüpfen. Wir könnten die Komponententests langsam einführen, wenn wir Fehler beheben und mehr Funktionen hinzufügen.
Es besteht jedoch die Sorge, dass die Aufrechterhaltung dieses Schemas (zusammen mit allen erforderlichen Stub-Funktionen) zu mühsam wird und die Entwickler die Wartung der Komponententests einstellen. Ein anderer Ansatz besteht darin, ein Tool zu verwenden, das automatisch Stubs für den gesamten Code generiert und die Datei damit verknüpft. (Das einzige Tool, das wir gefunden haben, um dies zu tun, ist ein teures kommerzielles Produkt.) Dieser Ansatz scheint jedoch zu erfordern, dass unser gesamter Code modularer ist, bevor wir überhaupt beginnen können, da nur die externen Aufrufe gelöscht werden können.
Persönlich möchte ich Entwickler lieber über ihre externen Abhängigkeiten nachdenken lassen und intelligent ihre eigenen Stubs schreiben. Dies könnte jedoch überwältigend sein, um alle Abhängigkeiten für eine schrecklich überwachsene Datei mit 10.000 Zeilen zu beseitigen. Es mag schwierig sein, Entwickler davon zu überzeugen, dass sie Stubs für alle ihre externen Abhängigkeiten verwalten müssen, aber ist das der richtige Weg, dies zu tun? (Ein weiteres Argument, das ich gehört habe, ist, dass der Betreuer eines Subsystems die Stubs für sein Subsystem verwalten sollte. Aber ich frage mich, ob das "Erzwingen" von Entwicklern, ihre eigenen Stubs zu schreiben, zu besseren Unit-Tests führen würde?)
Das #ifdefs
fügt dem Problem natürlich eine weitere ganze Dimension hinzu.
Wir haben uns mehrere C / C ++ - basierte Unit-Test-Frameworks angesehen, und es gibt viele Optionen, die gut aussehen. Wir haben jedoch nichts gefunden, was den Übergang von "Haarball des Codes ohne Unit-Tests" zu "Unit-testbarem Code" erleichtern könnte.
Hier sind meine Fragen an alle anderen, die dies durchgemacht haben:
- Was ist ein guter Ausgangspunkt? Gehen wir in die richtige Richtung oder fehlt uns etwas Offensichtliches?
- Welche Tools könnten hilfreich sein, um den Übergang zu erleichtern? (vorzugsweise Free / Open Source, da unser Budget derzeit ungefähr "Null" ist)
Beachten Sie, dass unsere Build-Umgebung auf Linux / UNIX basiert, sodass wir keine Nur-Windows-Tools verwenden können.