Hinzufügen von Komponententests zu einem älteren, einfachen C-Projekt

12

Der Titel sagt alles. Mein Unternehmen verwendet ein älteres Firmware-Projekt für ein Mikrocontroller-Gerät, das vollständig in C geschrieben ist.

Es gibt Teile, die offensichtlich falsch sind und geändert werden müssen, und die aus einem C # / TDD-Hintergrund stammen. Ich mag die Idee nicht, Dinge ohne Tests zufällig umzugestalten, um sicherzustellen, dass die Funktionalität unverändert bleibt. Ich habe auch gesehen, dass schwer zu findende Fehler in vielen Fällen durch geringste Änderungen eingeführt wurden (was meiner Meinung nach behoben werden würde, wenn Regressionstests verwendet würden). Es muss sehr sorgfältig vorgegangen werden, um diese Fehler zu vermeiden: Es ist schwierig, eine Reihe von Globals um den Code herum zu verfolgen.

Zusammenfassen:

  • Wie können Sie vor dem Refactoring Unit-Tests zu vorhandenem eng gekoppeltem Code hinzufügen?
  • Welche Tools empfehlen Sie? (weniger wichtig, aber trotzdem schön zu wissen)

Ich bin nicht direkt am Schreiben dieses Codes beteiligt (meine Verantwortung ist eine App, die auf verschiedene Weise mit dem Gerät interagiert), aber es wäre schlecht, wenn gute Programmierprinzipien zurückgelassen würden, wenn die Möglichkeit bestünde, dass sie verwendet werden könnten.

Groo
quelle

Antworten:

7

Holen Sie sich eine Kopie von Working Effectively With Legacy Code von Michael Feathers. Es soll mit solchen Situationen umgehen. Obwohl es sich mehr auf OO-Sprachen wie C ++ und Java konzentriert, glaube ich, dass es Ihnen immer noch sehr helfen kann.

Es sieht so aus, als ob ein Teil davon (oder ein früher Artikelentwurf) hier sogar kostenlos erhältlich ist .

Péter Török
quelle
+1, danke. Aber ich glaube, ich bin ziemlich gut darin, OO-Code mit mehr OO-Code umzugestalten. Was ich nicht weiß, ist, wie man Verfahrenscode testet und Verfahrenscode mit weniger gekoppeltem Verfahrenscode umgestaltet.
Groo
@Groo, in dem Buch geht es nicht um Refactoring an sich. Es geht darum, wie man eine Reihe von Spaghetti-Code ohne Unit-Tests in eine Reihe von (etwas weniger Spaghetti) Code umwandelt, die gut mit Unit-Tests abgedeckt sind. Ein solcher Code ist schwer zu testen, daher müssen Sie ihn zuerst umgestalten, um ihn testbar zu machen. Wie Sie ebenfalls erwähnt haben, ist das Refactoring ohne Unit-Tests jedoch riskant, sodass es sich um eine Catch-22-Situation handelt. Das Buch zeigt Ihnen, wie Sie die kleinsten und sichersten Änderungen am Code vornehmen, die es Ihnen ermöglichen, ihn mit Komponententests abzudecken, und anschließend ernsthaft mit der Umgestaltung beginnen.
Péter Török
Dieses Buch ist ein guter Vorschlag und behandelt C zusammen mit OO-Sprachen.
ThomasW
7

Für Techniken wird das Buch von Michael Feathers in Péter Töröks Antwort wahrscheinlich ziemlich umfassend sein. Wenn Sie nicht zum Buch gehen möchten, schlage ich einen dreistufigen Prozess vor:

  1. Untersuchen Sie den nicht testbaren Code und duplizieren Sie kleine Teile der Funktionalität dieses Codes in testbare Funktionen. Es ist wichtig, dass die neuen Funktionen ein Verhalten aufweisen, das offensichtlich der Funktion entspricht, die Sie duplizieren möchten. Ich befürworte eigentlich nicht, Unit-Tests um den Legacy-Code herum zu schreiben. Sie müssen also sehr vorsichtig sein und Ihren Umfang einschränken um das Vertrauen in das Refactoring aufrechtzuerhalten.
  2. Schreiben Sie Unit-Tests um diese neuen Funktionen.
  3. Ändern Sie den ursprünglichen Code, um die neuen Funktionen aufzurufen.

Wiederholen Sie diesen Vorgang einige Male, und Sie sollten feststellen, dass die Qualität der Legacy-Codebasis erheblich gestiegen ist.

Beachten Sie, dass C ++ C aufrufen kann, sodass jedes C ++ - Framework für Unit-Tests zum Testen von C-Code verwendet werden kann. Zum Beispiel verwenden wir CPPUnit , um eine Reihe von C-Code in unserem Projekt zu testen.

Aidan Cully
quelle
+1 danke für die Tipps und den CPPUnit- Link.
Groo