Guten Abend, ich habe ein C-Projekt (Ansi C), das aus mehreren .c und .h Dateien besteht. Die C-Funktionen in diesem Projekt tauschen untereinander Daten aus, so dass es Eingangs- und Ausgangswerte gibt, die auf Korrektheit überprüft werden können. Vereinfacht führt eine C-Funktions eine Addition von input1 und input2 mit folgendem Testcode durch: Schreibe: input1=1; input2=2; Lese: output=x; Vergleiche: output==3? Frage: Mit welchem Ansatz (Script, Tool, Software-Debugger etc.) würde man diese Aufgabe lösen, sprich wo läuft der Testcode und wo der vorhandene C-Code? Dino.
Dieses ist ein Black-Box Test, sprich Daten gehen rein und raus. Bei Unit-Tests handelt es sich per Definition um White-Box Tests.
Dino schrieb: > Dieses ist ein Black-Box Test, sprich Daten gehen rein und raus. > Bei Unit-Tests handelt es sich per Definition um White-Box Tests. Das stimmt nicht, sry. Unit Tests sind Black-Box tests.
Rene H. schrieb: > Das stimmt nicht, sry. Unit Tests sind Black-Box tests. Unter Modultests verstehe ich Zweigüberdeckung etc. und hier möchte ich ja auch Modulübergreifend testen, also nicht nur ein Modul. Aber bei Wikipedia habe ich jetzt auch gelesen, dass ein Modultests testen gemäß dem Design-by-contract-Prinzip auch ein Black-Box Test ist. Ok. Beispielsweise übergebe ich argumente in den Schnittstellen-Funktionen und bekomme am Ende irgendwo ein Return-Value in einem anderen Modul (wie ist das überhaupt definiert?) als Ergebnis zurück, wie wäre das einer Testart zuzuordnen?
Dino schrieb: > Unter Modultests verstehe ich Zweigüberdeckung etc. und hier möchte ich > ja auch Modulübergreifend testen, also nicht nur ein Modul. Das ist ziemlich egal, wieviel da drin hängt, solange der Einsprungspunkt dem Rückgabepunkt entspricht.
Rene H. schrieb: > Das ist ziemlich egal, wieviel da drin hängt, solange der > Einsprungspunkt dem Rückgabepunkt entspricht. und wie/womit würde man das testen?
Auf dem Internet wirst Du sicher welche finden. Meine kann ich leider nicht zur Verfügung stellen. Schau dir mal Nose an, dass verwende ich. Da gibts auch viele gute Beispiele.
Dino schrieb: > Frage: Mit welchem Ansatz (Script, Tool, Software-Debugger etc.) würde > man diese Aufgabe lösen, sprich wo läuft der Testcode und wo der > vorhandene C-Code? C ist keine Interpretersprache, man kann also interne Funktionen nicht einfach per Testscript aufrufen. Der Testscript muss also in C geschrieben und hinzukompiliert werden, als eigenständig lauffähiges Testprogramm. Statt main des eigentlichen Programms wird also main des Testrahmenprogramms aufgerufen, in dem so etwas wie:
1 | test.c: |
2 | int main(void) |
3 | { |
4 | input1=1; |
5 | input2=2; |
6 | output=Testfunktion(input1,input2); |
7 | assert(output==3); |
8 | } |
Da assert das Programm bei Fehler unter Nennung einer Zeilennummer abbricht, kann ein if mit printf nützlicher sein: Dann werden auch die nachfolgenden Tests ausgeführt. Gegen Fehler im Testprogramm selber hilft try catch.
Als Testsuite für C finde ich Ceedling recht schick. http://www.throwtheswitch.org/ceedling Das läuft allerdings mit Rakefiles (Ruby).
Ich verstehe noch nicht, warum ich ein Testframework brauche und der Vorschlag von MaWin nicht alleine ausreicht? Was sind die Vorteile davon?
CppCon 2015: Matt Hargett “Advanced Unit Testing in C & C++” https://youtu.be/Wmy6g-aVgZI?list=PLHTh1InhhwT75gykhs7pqcR_uSiG601oh cppunit https://freedesktop.org/wiki/Software/cppunit/ cgreen https://github.com/cgreen-devs/cgreen Dino schrieb: > Ich verstehe noch nicht, warum ich ein Testframework brauche Brauchen tut man das nicht. Aber : Du bist nicht der Erste mit diesem Problem, und auch nicht der Letzte. Und da haben sich schon mal tausende von Entwicklern weltweit gedanken zu gemacht. Dadurch sind halt Werkzeuge entstanden, Testframeworks, die mittlerweile ebenfalls tausendfach erprobt sind und die sich bewährt haben. Warum willst du das Rad selber neu erfinden, und in all die Fallen laufen, in die schon mal andere gelaufen sind, die die Fallen dann aus dem Weg geräumt haben? Dino schrieb: > Was sind die Vorteile davon? Du hast 5000 Test, und alle sind vom Ablauf und der Syntax gleich. verstehst du einen Test, verstehst du alle 5000. Bastelst du dir selber was, hast du nachher 5000 verschiedene Abläufe, alle mit anderer Syntax, und jemand (inklusive dir selbst!), der sich deine Test später mal anschaut, muss bei jedem Test wieder ganz von vorne anfangen zu überlegen, was du eigentlich gerade vorhast... Dino schrieb: > Mit welchem Ansatz (Script, Tool, Software-Debugger etc.) Du fragst nach Tools, dann werden dir die üblichen Tools/vorgehensweisen genannt, und dann fragst du, wozu man das braucht... Du kannst einen Nagel auch mit einem Stein ins Holz treiben, mit 'nem Hammer gehts dann aber vielleicht doch etwas besser und leichter.
Testframeworks C https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C Testframeworks C++ https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B
Dino schrieb: > Ich verstehe noch nicht, warum ich ein Testframework brauche und der > Vorschlag von MaWin nicht alleine ausreicht? Was sind die Vorteile > davon? Bei Unit Tests hat man eine Reihe unabhängiger Testcases, die alle in unbekannter Reihenfolge ausgeführt werden. Am Ende sieht man bei den Testframeworks von jedem Test ob er durchlief, und welche Annahmen fehlgesclagen sind. MaWins variante wird beim ersten Testcase bei einem Fehler beendet, und man sieht nichtmehr von jedem Testcase ob er noch geht. Zusäzlich können einige Tools die code coverage anzeigen, also welche Codezeilen getestet sind und welche nicht. Natürlich können Tests nicht alle Fehler aufdecken, z.B. kann es passieren, das man eine Situation, die man vergist zu implementieren, davir auch vergessen hat, zu testen. Oder dass ein Fehler nur unter bestimmten Laufzeitbedingungen auftritt, und deshalb in den Tests nicht auffallen. Alles schon erlebt.
Es ist generell eine gute Idee die requirements als erstes in test cases zu giessen und dann erst mit der Implementierung der eigentlichen Funktion zu beginnen. Dass erlaubt dann in der Edit/compile loop sehr schnelles Feedback wenn man dabei gleich die Tests ausführt.
Scheue mich vor einem Testframework, die vielen Files (GMock etc.) sehen für mich nach Frickel-Arbeit aus, bis alles läuft. Gibt es eine fertige Lösung (Eclipse etc.), wo ich die C-Sourcen hinzufüge, kompilieren kann und ein Testframework an Board habe?
Dino schrieb: > Scheue mich vor einem Testframework, die vielen Files (GMock etc.) sehen > für mich nach Frickel-Arbeit aus, bis alles läuft. > Gibt es eine fertige Lösung (Eclipse etc.), wo ich die C-Sourcen > hinzufüge, kompilieren kann und ein Testframework an Board habe? Testen ohne Aufwand gibt's nicht. Will sagen, eine Testumgebung einzurichten geht nicht mit zwei drei Mausklicks. Beispiel Eclipse: https://www.evernote.com/shard/s226/sh/45f4e966-2a41-425f-9f56-b1d924eef186/870714cbfbe6ad8480bdb1effd72edcf Beispiel NetBeans: https://netbeans.org/kb/docs/cnd/c-unit-test.html
:
Bearbeitet durch User
Daniel A. schrieb: > Bei Unit Tests hat man eine Reihe unabhängiger Testcases, die alle in > unbekannter Reihenfolge ausgeführt werden. Ich vermute ja mal, dass es sich nur um eine unglückliche Formulierung handelt, aber unerwähnt lassen sollten wir das dennoch nicht: Ein Test, bei dem ein relevanter Parameter unbekannt ist, ist sicher kein sehr guter Test. Die Reihenfolge der Testfälle muss nur variieren, wenn ich befürchten muss, dass sie einen Einfluss auf das Testergebnis hat. (Wobei es sicher nicht schadet, das grundsätzlich erst einmal anzunehmen bzw. das auch zu testen selbst wenn ich glaube, dass sie keinen Einfluss hat.) Wenn nun der Test aber einen Fehler erkennt, der nur bei einer bestimmten Reihenfolge auftritt, die ich aber nicht kenne, ich den Fehler also nicht reproduzieren kann, dann wird mir das nur wenig helfen, den Fehler zu finden und zu beseitigen. Sagen wir also lieber, die Testcases werden in verschiedenen, idealerweise in allen mögliche Reihenfolgen abgearbeitet (wobei der Aufwand dann natürlich exponentiell mit der Anzahl der Testfälle wächst).
A. H. schrieb: > Daniel A. schrieb: >> Bei Unit Tests hat man eine Reihe unabhängiger Testcases, die alle in >> unbekannter Reihenfolge ausgeführt werden. > > Ich vermute ja mal, dass es sich nur um eine unglückliche Formulierung > handelt, aber unerwähnt lassen sollten wir das dennoch nicht: Ein Test, > bei dem ein relevanter Parameter unbekannt ist, ist sicher kein sehr > guter Test. Nein, ich habe dies Absichtlich so formuliert. Jeder Testcase muss voneinander vollständig unabhängig sein. Die Reihenfolge darf niemals ein relevanter Parameter werden, sonnst ist entweder der Testcase unvollständig, oder das Programm hat einen Designfehler und das Programmdesign muss angepasst werden. A. H. schrieb: > Sagen wir also lieber, > die Testcases werden in verschiedenen, idealerweise in allen mögliche > Reihenfolgen abgearbeitet (wobei der Aufwand dann natürlich exponentiell > mit der Anzahl der Testfälle wächst). Vermutlich ist mir deshalb kein Testframework bekannt, welches dies tut. Die Tests würden zu lange dauern.
Daniel A. schrieb: >... > Vermutlich ist mir deshalb kein Testframework bekannt, welches dies tut. Junit hat das lange Zeit erlaubt, aber generell sollen unit tests tatsächlich völlig unabhängig lauffähig sein. Braucht man eine bestimmte Reihenfolge gibt es nur den Weg einen Satz Tests sequentiell von einer Testfunktion aufrufen zu lassen.
Daniel A. schrieb: > Bei Unit Tests hat man eine Reihe unabhängiger Testcases, die alle in > unbekannter Reihenfolge ausgeführt werden. Worüber ich hier gestolpert bin ist die Formulierung „in unbekannter Reihenfolge“. Natürlich sind in einem guten Design die Funktionen eines Moduls idealerweise seiteneffektfrei, insbesondere also unabhängig von der Geschichte der Aufrufe. Dann sind auch die Tests in diesem Sinne unabhängig, also unabhängig von ihrer Reihenfolge. Dann macht es aber auch keinen Sinn, die Reihenfolge zum Gegenstand der Diskussion zu machen, insbesondere zu fordern – so zumindest lese ich diese Formulierung – dass ihre Reihenfolge unbekannt sein soll. Darüber hinaus kann ich mir eigentlich gar keine Situation vorstellen, in der es sinnvoll wäre zu fordern, dass eine Randbedingung eines Tests unbekannt ist. Je mehr ich über einen Tests weiß, je besser ist es, und das gilt meines Wissens nach immer. Andererseits sind nun mal nicht alle Module seiteneffektfrei. Dann muss ich die Reihenfolge zu einem Testparameter machen. Nun kann man argumentieren, dass dann jede zu testende Reihenfolge ein eigener Testfall ist und diese Testfälle wechselseitig wieder unabhängig sind – einverstanden. Mein Grundproblem aber bleibt: Entweder die Reihenfolge ist wichtig, dann muss sie bekannt sein, oder sie ist es nicht, dann muss ich nicht darüber reden; aber selbst dann ist es immer noch besser, sie zu kennen. Eine unbekannte Reihenfolge aber ist in keinem Fall wünschenswert oder gar notwendig. Aber wie gesagt, ich denke, das war nur eine etwas unglückliche Formulierung.
A. H. schrieb: > Mein Grundproblem aber bleibt: Entweder die Reihenfolge > ist wichtig, dann muss sie bekannt sein, oder sie ist es nicht, dann > muss ich nicht darüber reden; aber selbst dann ist es immer noch besser, > sie zu kennen. Eine unbekannte Reihenfolge aber ist in keinem Fall > wünschenswert oder gar notwendig. Aber wie gesagt, ich denke, das war > nur eine etwas unglückliche Formulierung. Es gibt Frameworks, die führen Tests in "zufälliger" Reihenfolge, geben dann aber im Fehlerfall den seed für den RNG mit aus und erlauben so die Wiederholung in genau dieser Reihenfolge. Die Reihenfolge ist somit zufällig und bekannt :-) Hier ein Beispiel, bei dem man dass auch wieder abschalten kann (was zum Schmunzeln): http://ruby-doc.org/stdlib-1.9.3/libdoc/minitest/unit/rdoc/MiniTest/Unit/TestCase.html#method-c-i_suck_and_my_tests_are_order_dependent-21
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.