Forum: PC-Programmierung Frage zum C-Code testen


von Dino (Gast)


Lesenswert?

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.

von Sven B. (scummos)


Lesenswert?

...hä?

von Rene H. (Gast)


Lesenswert?

Du meinst vermutlich Unit Tests? Richtig?

von Dennis S. (eltio)


Lesenswert?

asserts?

von Dino (Gast)


Lesenswert?

Dieses ist ein Black-Box Test, sprich Daten gehen rein und raus. Bei 
Unit-Tests handelt es sich per Definition um White-Box Tests.

von Rene H. (Gast)


Lesenswert?

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.

von Dino (Gast)


Lesenswert?

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?

von Rene H. (Gast)


Lesenswert?

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.

von Dino (Gast)


Lesenswert?

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?

von Rene H. (Gast)


Lesenswert?

Ich verwende dafür Python.

von Dino (Gast)


Lesenswert?

gibts da Beispiele?

von Rene H. (Gast)


Lesenswert?

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.

von MaWin (Gast)


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

Das ist zwar C++, kann man aber sicher mit c kombinieren:
https://github.com/google/googletest

von Bernhard R. (bernhard_r28)


Lesenswert?

Als Testsuite für C finde ich Ceedling recht schick.
http://www.throwtheswitch.org/ceedling

Das läuft allerdings mit Rakefiles (Ruby).

von Dino (Gast)


Lesenswert?

Ich verstehe noch nicht, warum ich ein Testframework brauche und der 
Vorschlag von MaWin nicht alleine ausreicht? Was sind die Vorteile 
davon?

von Kaj (Gast)


Lesenswert?

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.

von Kaj (Gast)


Lesenswert?


von Daniel A. (daniel-a)


Lesenswert?

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.

von The D. (thedaz)


Lesenswert?

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.

von Dino (Gast)


Lesenswert?

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?

von Mark B. (markbrandis)


Lesenswert?

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
von A. H. (ah8)


Lesenswert?

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).

von Daniel A. (daniel-a)


Lesenswert?

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.

von The D. (thedaz)


Lesenswert?

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.

von A. H. (ah8)


Lesenswert?

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.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

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
Noch kein Account? Hier anmelden.