Guten morgen,
wie geht ihr bei Unittests mit statischen funktionen um?
Testet ihr diese? Ich bin gerade mit cmocka gestartet und möchte
Unittests für mein Projekt erstellen.
Das Problem ist ja, dass diese Funktion aus einer anderen Datei (test.c)
aufgerufen wird und damit ja eigentlich nicht mehr statisch ist.
Das einzige was mir einfällt ist ein Define zu erstellen und in file1.h
1
#ifdef TEST
2
voidfunction(void)
3
#endif
und in file1.c
1
#ifdef TEST
2
definestaticTest
3
#else
4
definestaticteststatic
5
#endif
6
7
#ifndef TEST
8
staticvoidfunction(void);
9
#endif
10
...
11
...
12
staticTestvoidfunction(void)
Dann wird es aber für mehrere Funktionen sehr unübersichtlich und man
müsste ja auch den eigentlichen Code dahin anpassen.
Gibt es noch andere möglichkeiten?
Verstehe ich nicht ganz. Ein Unittest testet doch ein Modul an seinen
Schnittstellen. Die statische Funktion gehört da nicht dazu, da sie von
außen ja gar nicht sichtbar ist.
Rolf M. schrieb:> Verstehe ich nicht ganz. Ein Unittest testet doch ein Modul an seinen> Schnittstellen. Die statische Funktion gehört da nicht dazu, da sie von> außen ja gar nicht sichtbar ist.
Du gehst davon aus, dass Eine Unit immer eine C-Datei ist.
Das ist nur bei kleinen Projekten so.
MaWin schrieb:> Rolf M. schrieb:>> Verstehe ich nicht ganz. Ein Unittest testet doch ein Modul an seinen>> Schnittstellen. Die statische Funktion gehört da nicht dazu, da sie von>> außen ja gar nicht sichtbar ist.>> Du gehst davon aus, dass Eine Unit immer eine C-Datei ist.> Das ist nur bei kleinen Projekten so.
Entweder die statische Funktion ist nur ein "kleiner, unbedeutender"
Helfer (Implementierungsdetail), dann teste ich ihre Funktion implizit
dadurch, dass das öffentlich zugängliche Interface die Funktion
implementiert, die ich sehe möchte, oder sie stellt einen Nutzen zur
verfügung, der Dokumentiert ist (sonst kann ich sie auch nicht testen),
dann muss ich sie auch nicht static machen.
MaWin schrieb:> Rolf M. schrieb:>> Verstehe ich nicht ganz. Ein Unittest testet doch ein Modul an seinen>> Schnittstellen. Die statische Funktion gehört da nicht dazu, da sie von>> außen ja gar nicht sichtbar ist.>> Du gehst davon aus, dass Eine Unit immer eine C-Datei ist.
Nö, die kann auch aus 100 C-Dateien bestehen. Dann ist die Funktion
trotzdem nicht von außen sichtbar.
Torsten R. schrieb:> dann muss ich sie auch nicht static machen.
Und was ist, wenn ich sie nur intern im Modul verwende, sie aber
trotzdem funktional eigenständig ist?
g457 schrieb:> Und für aller Testverweigerer: Ja, man will unbedingt auch die nur lokal> verfügbaren ("statischen") Funtionen testen.
Dann würde ich allerdings nicht mehr von Unittests sprechen.
Rolf M. schrieb:> Nö, die kann auch aus 100 C-Dateien bestehen. Dann ist die Funktion> trotzdem nicht von außen sichtbar.
Und was ist, wenn eine C-Datei 3 Units beinhaltet?
MaWin schrieb:> Torsten R. schrieb:> Und was ist, wenn ich sie nur intern im Modul verwende, sie aber> trotzdem funktional eigenständig ist?
Na, dann könntest Du Sie doch trotzdem testen. Kommt im Detail dann aber
auch darauf an, was Du unter "intern im Modul" verstehst. Wenn dass
Modul aus 20kLOC besteht, dann hat die Funktion sicher nicht mehr
interne Linkbarkeit und hat ein wohl definierte Funktionalität, die
Dokumentiert und testbar ist. Wenn es eine kleine Helfer-Funktion ist,
die einen String in Großbuchstaben konvertiert, dann gehört sie in die
Tool-Box und wird dort getestet.
Ich hatte noch nie das Bedürfnis, eine statische Funktion zu testen (das
Gleiche gilt für private member functions). Kann man jemand eine
konkretes Beispiel geben?
MaWin schrieb:> Und was ist, wenn eine C-Datei 3 Units beinhaltet?
Dann sollte man das ändern.
MaWin schrieb:> Rolf M. schrieb:>> Dann würde ich allerdings nicht mehr von Unittests sprechen.>> sondern?
Weiß ich nicht. Aber für mich bedeutet Unittest folgendes:
Ich habe ein Modul, das ich als Black Box betrachte. Es bietet nach
außen definierte Schnittstellen und ein dokumentiertes Verhalten an. Nun
teste ich an diesen Schnittstellen, ob sich das Modul als ganzes auch
tatsächlich wie spezifiziert verhält. Da interessieren mich interne
Funktionen eben nicht. Wie würdest du es definieren?
Rolf M. schrieb:> Weiß ich nicht. Aber für mich bedeutet Unittest folgendes:> Ich habe ein Modul, das ich als Black Box betrachte. Es bietet nach> außen definierte Schnittstellen und ein dokumentiertes Verhalten an. Nun> teste ich an diesen Schnittstellen, ob sich das Modul als ganzes auch> tatsächlich wie spezifiziert verhält. Da interessieren mich interne> Funktionen eben nicht. Wie würdest du es definieren?
Unittests muss man aber nicht als Black-Box-Tests machen. Wenn ich weiß,
dass es in der Implementierung irgend ein kritischen Pfad gibt, dann
will ich den ja unbedingt testen (z.B. irgend eine alternative Strategie
unter bestimmten Bedingungen).
Test von kleinsten Einheiten: Unit-Tests
Test des Zusammenspiels von kleinsten Einheiten: Integration-Tests
Rolf M. schrieb:> Weiß ich nicht. Aber für mich bedeutet Unittest folgendes:> Ich habe ein Modul, das ich als Black Box betrachte.
Unittests sind white-box-tests.
Neben der Prüfung des output vectors (z.B. Rückgabewert, manipulierte
globable Symbole etc.) werden im Rahmen von Unittests auch Metriken wie
Code-/Branch-/Decision-coverage überprüft.
Das klappt nicht bei Blackboxen.
Torsten R. schrieb:> Ich hatte noch nie das Bedürfnis, eine statische Funktion zu testen (das> Gleiche gilt für private member functions). Kann man jemand eine> konkretes Beispiel geben?
Das hat man häufig bei Embedded-SW wo ein Modul eine Funktion hat die
zyklisch vom RTOS aufgerufen werden muss.
Wenn diese zyklische Funktion mehrere thematisch unabhängige
Teilaufgaben bearbeitet kann es aus Gründen der Übersichtlichkeit
durchaus Sinn machen, diese Funktion intern aufzusplitten (z.B.
CheckInput(), DoSomething(), WriteOutput()).
Man zerlegt also einen Task in mehrere Kleinere.
Kommt durchaus häufig vor.
Le X. schrieb:> Unittests sind white-box-tests.
Jupp, ich sag eher:
Unittests können beides: black und auch white-box-tests.
In Bereichen in denen Codecoverage Tests gefordert werden
(FuSi...) müssen auch static Funktionen getestet werden.
Und tatsächlich hatten wir kritischere Fehler bei static Funktionen
als bei von außen zugreifbaren Funktionen.
Ich hatte auch schon einen Kollegen der
alles mögliche auf static gesetzt hat, damit er es nicht testen muss....
:-)
Rolf M. schrieb:> MaWin schrieb:>> Rolf M. schrieb:>>> Dann würde ich allerdings nicht mehr von Unittests sprechen.>>>> sondern?>> Weiß ich nicht. Aber für mich bedeutet Unittest folgendes:> Ich habe ein Modul, das ich als Black Box betrachte. Es bietet nach> außen definierte Schnittstellen und ein dokumentiertes Verhalten an. Nun> teste ich an diesen Schnittstellen, ob sich das Modul als ganzes auch> tatsächlich wie spezifiziert verhält. Da interessieren mich interne> Funktionen eben nicht. Wie würdest du es definieren?
Da hast du jetzt eine "Unit" mit einer möglichen Definition von Modul
gleichgesetzt. Wer sagt, dass eine Unit nicht eine Funktion ist? Alles
was du in dem zitierten Absatz geschrieben hast, kann man auch auf eine
Funktion als "Unit" anwenden.
Meines Erachtens scheidet das überschreiben von static aus. Ich würde
immer Mawins Ansatz (Unit-Tests von innen) bevorzugen, auch wenn der
Testcode dann im Quelltext steht.
Man könnte alternativ auch definieren, dass der Test in den öffentlichen
Funktionen aufgehen muss. Dass also static-Funktionen prinzipiell nur
Code haben, der auch durchlaufen wird, dann braucht es keinen
gesonderten Test (100%-Testabdeckung durch die anderen Unit-Tests).
Eine dritte Möglichkeit wäre, dass man den Code per Include in eine neue
C-Datei lokal zieht und um die notwendigen Tests ergänzt.