unit tests und malloc
-
Hallo Leuts, ich bin beim schreiben meiner ersten Unit tests auf eine Frage bezüglich malloc gestoßen.
Ich habe eine Funktion mit der Schnittstelle:
dfa_t *dfa_new(void);
Diese verwendet intern malloc und gibt bei ungenügend verfügbarem Speicher NULL zurück. Ich will nun die korrekte initialisierung der zurückgegebenen Struktur prüfen. Wie gehe ich mit so einer Funktion bei unit tests um? Wenn die reservierung des Speichers fehlschlägt ist das ja nicht ein Fehler der Funktion. Der Test schlägt ja damit im eigentlichen Sinne nicht fehl. Er ist aber auch nicht ausführbar. Da nichts da ist ,was geprüft werden könnte. Ein assert kommt aus meiner sicht somit nicht in Frage. Aber was dann? Soll ich das Testprogamm einfach mit exit(EXIT_FAILURE) beenden?
Genauer benutze ich übrigens CUnit.
Martin
-
Ja herzlichen Glückwunsch.
Sie sind einer der gaaanz wenigen Entwickler, die automatische Testfälle für C schreiben. Das wird sich aber in jedem Fall auszahlen, zumindestens bei größeren Umfängen.
Du wirst um das assert bzw. du meinst wohl CU_ASSERT nicht herumkommen, aber schon hier weist dich das Schreiben des Testfalls auf verkorkstes Design hin:
eine Funktion sollte immer genau das machen, wozu sie gedacht ist und sich nicht um Nebensächlichkeiten (hier das Definieren von Speicher) kümmern müssen, das ist Aufgabe eine anderen Funktion; deshalb kapselt man unterschiedliche Funktionalitäten auch sinnvollerweise in unterschiedliche Funktionen, in deinem Fall würde also dann die separierte Funktion zum Reservieren von Speicher fehlschlagen, die Suite würde dann eh abgebrochen werden müssen, und an den TF-Resultaten siehst du sofort, dass eben die Speicher-Funktion abbrach und hast sofort einen aussagekräftigen Testlauf.
Schreibe dir einen eigenen Speichermanager, der kann erstmal gaaanz einfach sein, und verwende nur diesen bzw. nur Instanzen von diesem, glaube mir, das lohnt sich, nicht nur im Hinblick von Testfällen.
Solange C noch keine GarbageCollection hat;-) ist es eh nie ratsam, malloc/free in unterschiedlichen Programmkontexten zu implementieren, also so wie bei dir, dass die Funktion intern Speicher definiert, der im aufrufenden (und somit anderen) Kontext freigegeben werden muss, malloc/free sollten zumindest auf einer Ebene der Aufrufkontexte liegen, und auch hier kann dir ein Speichermanager schnell evtl. Leaks anzeigen. Übergebe deiner Funktion zuvor fertig definierten Speicher und lass sie dann darauf rumwerkeln.
Die nächste Stufe wäre für dich dann TDD, glaube mir, das wird dir gefallen, und weist dich wie o.g. schon beim Designen auf Fehler hin.
-
Hi,
Du meinst also, dass ich zwei seperate Funktionen haben sollte.Also z.B:
dfa_t *dfa_new(void); void dfa_init(dfa_t *dfa);
Mh. Stimmt. Dann könnte ich nur auf dfa_init testen, und dfa_new als Vorraussetzung für den Test betrachteten und in die Initialisierungsfunktion packen.
Für den Endnutzer dann noch eine dfa_create Funktion die die beiden obigen hintereinander ausführt.Ist zwar ein wenig Extracode, aber immer noch besser als sich ständig mit dem Debugger zu quälen.
-
Und wenn es eine Art opaque Handle sein soll. ... Der Fehlerfall bei zu wenig Speicher ist eben nicht testbar, bzw. nicht mit vertretbarem Aufwand. Wieviele Funktionen sollen denn noch geschrieben warden, um eine einfache kleine Sache zu erreichen?
-
Hey Wutz,
was meinst du eigentlich genau mit "eigener Speichermanager". Welche Aufgaben soll denn dieser erfüllen?
Danke,
Martin
-
Ja herzlichen Glückwunsch.
Sie sind einer der gaaanz wenigen Entwickler, die automatische Testfälle für C schreiben. Das wird sich aber in jedem Fall auszahlen, zumindestens bei größeren Umfängen.Ähh ja...