wie statische funktionen im unittest testen

Gast #6607118
Lesenswert?

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
void function(void)
3
#endif
und in file1.c
1
#ifdef TEST
2
define staticTest
3
#else
4
define statictest static
5
#endif
6

7
#ifndef TEST
8
static void function(void);
9
#endif
10
...
11
...
12
staticTest void function(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?
Gast #6607138
Lesenswert?

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.
(Firma: Torrox.de) #6607151
Lesenswert?

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.
Gast #6607153
Lesenswert?

> Gibt es noch andere möglichkeiten?

Fast so wie oben, nur wesentlich einfacher:

common.h
1
#ifdef UNITTEST
2
  #define STATIC
3
#else // UNITTEST
4
  #define STATIC static
5
#endif // UNITTEST

file.c
1
#include <common.h>
2
[..]
3
STATIC void foo(void);
4
STATIC T bar(T2);
5
[..]
6

7
STATIC void foo(void)
8
{ [..] }
9

10
STATIC T bar(T2);
11
{ [..] }

Und für aller Testverweigerer: Ja, man will unbedingt auch die nur lokal 
verfügbaren ("statischen") Funtionen testen.
#6607155
Lesenswert?

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.
(Firma: Torrox.de) #6607168
Lesenswert?

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?
#6607173
Lesenswert?

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?
(Firma: Torrox.de) #6607179
Lesenswert?

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
#6607381
Lesenswert?

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.
#6608280
Lesenswert?

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.... 
:-)
Gast #6608284
Lesenswert?

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.
Gast #6608290
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren