Basic Unit Test und C, wie fange ich an?

Lesezeit: 6 Minuten

Benutzer-Avatar
Johann

Nachdem ich einige Threads hier bei StackOverflow gelesen habe, bin ich zu dem Schluss gekommen, dass ich mich einer Form von testgetriebener Entwicklung/Einheitentest zuwenden sollte (oder zumindest den Bereich erkunden sollte).

Und da wir über C-Code unter Linux sprechen, habe ich mich entschieden zu geben überprüfen einen Versuch (ich weiß nicht, ob das die richtige Wahl ist, aber wenn es nicht gut ist, kann ich später immer noch etwas anderes versuchen).

Aber da dieses Konzept von Unit-Tests und Unit-Test-Frameworks völlig neu für mich ist, habe ich angefangen, einige Unit-Tests an einem wirklich kleinen Testcode durchzuführen (aber ich war sowieso total verloren und es fühlte sich an, als würde mir etwas fehlen).

Das habe ich bisher gemacht, ich habe folgende Datei erstellt:

  • main.c, eine main, die nur eine Funktion namens my_pow aufruft und das Ergebnis ausgibt.
  • my_pow.c, enthält die Funktion my_pow.
  • mein_pow.h
  • my_pow_test.c, dachte ich, dass ich hier den Einheitencode für die my_pow-Funktion platzieren sollte.

(Das “normale Programm” ist also main.c, my_pow.c und my_pow.h.)

Das ist my_pow.c


#include "my_pow.h"
int my_pow(int a, int b)
{
    return (a*b);
}

Dann dachte ich mir, dass ich in my_pow_test.c so etwas einfüge:


#include <check.h>
#include "my_pow.h"

START_TEST (test_my_pow)
{
    /* unit test code */
}
END_TEST

//do I need some sort off main here that calls test_my_pow?

Das ist im Grunde dasselbe wie in das Prüfhandbuch Kapitel 3.1, aber immer noch nicht….

Könnte mich bitte jemand in die richtige Richtung schubsen?

Danke Johann


Update: Kein Grund, warum ich versucht habe, check zu verwenden. Ich dachte nur, ich sollte irgendwo anfangen, vielleicht ist CUnit die bessere Wahl (ich denke, ich würde das auch versuchen und dann eine fundierte Entscheidung treffen).

Update: Danke @philippe für den indirekten Hinweis, dass die Online-Dokumentation nur die halbe Wahrheit ist, der Beispielcode, der verdeutlicht, wovon die Dokumentation spricht, wurde bereits mit dem Check-Paket installiert. Im Ubuntu-Fall /usr/share/doc/check/example/tests/

Update: Das Codebeispiel wurde so erstellt, dass Sie sich zunächst seine erste Version ansehen, dann die zweite usw. usw. Damit Sie verfolgen können, wie er einen sehr einfachen Testfall/Code von nichts bis zu etwas Nützlichem erstellt ein traditioneller TTD-Weg.

Und da mein Code kaputt war und ich wollte, dass der Unit-Test dies beweist, habe ich ein wenig geschummelt und gegen die echte pow-Funktion getestet. Etwas wie das:


START_TEST (test_my_pow1)
{
    int resultat = my_pow(3,3);
    int math     = pow(3,3);
    fail_unless ( resultat == math,
           "Error on 3^3 != %d (%d)",math, resultat);
}

Allerdings werde ich in Zukunft nicht mehr reproduzieren, was bereits in den stdlibs steht 🙂


Verwandt:

  • C-Code für Unit-Tests
  • So testen Sie C-Code
  • Unit Testing Frameworks für C
  • Testframeworks für C
  • Basic Unit Test und C, wie fange ich an?

aus der Suche genommen [c] [unit-testing].

  • Wissen Sie, dass pow(a,b) != a*b ? 😉

    – Aif

    17. Januar 2009 um 13:07 Uhr

  • @Aif, ich denke, er weiß es. Aber um die Leistungsfähigkeit von Unit-Tests zu sehen und zu lernen, ist es keine schlechte Idee, mit einer fehlerhaften Funktion zu beginnen.

    – Quinmare

    17. Januar 2009 um 15:40 Uhr

Benutzer-Avatar
Philant

Sie haben einen ersten Testfall erstellt. Jetzt müssen Sie Erstellen Sie eine Testsuite (eine Gruppe von Testfällen) und a Läufer.

Ich würde empfehlen, dass Sie versuchen, zu kompilieren ihr Beispiel zuerst, um Ihre Umgebung zu validieren, obwohl ihre Dokumentation neuen Code über diff (Quell-Patch) einführt, was ich nicht sehr praktisch finde.


Wenn Sie sich jemals entscheiden, es mit einem anderen Framework zu versuchen (Mineinheit kam mir sofort in den Sinn), kann ich Sie auf eine “Lernprogramm“.

  • Die obigen Links sind nicht mehr aktuell … verwenden Sie stattdessen diese: Testsuite, Läufer

    – knacker123

    11. Februar 2016 um 13:34 Uhr


Da würde ich eher mitgehen CUnit das Teil der X-Unit-Reihe von Testframeworks ist.

Es ist für große Testsuiten skalierbar und wird seit vielen Jahren verwendet, daher ist es ausgereift.

Gibt es einen Grund, warum Sie sich nicht für CUnit entschieden haben?

HTH

Prost,

rauben

Benutzer-Avatar
dbyron

Ich habe verwendet dejagnu seit Jahren und liebe es.

Ich habe damit begonnen, es für die eingebettete Entwicklung zu verwenden, weil es sehr gut das Konzept unterstützt, dass die Maschine, auf der Sie das Testprogramm ausführen, möglicherweise anders ist als die Maschine, auf der Sie das Testprogramm erstellen. Als Folge davon wird auch das Testen von Code auf mehreren Plattformen gut unterstützt. Ich bin mir nicht sicher, ob das wichtig ist. Die gcc-Testsuite verwendet es. Ich benutze es auch für die Desktop-Entwicklung.

Die Grundidee von dejagnu ist, dass du

  • Kopieren Sie das Testprogramm in das “Ziel” (was für lokale Tests das ~/tmp-Verzeichnis sein könnte)
  • Testprogramm starten
  • Drucksachen an die Konsole (die als Eingabe für das Testprogramm dient)
  • Analysieren Sie die Ausgabe des Testprogramms und gleichen Sie sie mit Ihren Erwartungen ab
  • Entscheiden Sie, ob diese Ausgabe bestanden oder nicht bestanden bedeutet

Sobald Sie das Testprogramm und die Testskripte geschrieben haben, machen Sie am Ende so etwas:

$ runtest
                === foo Summary ===

# of expected passes            42
foo-test built Thu Jan 15 20:09:19 PST 2009
foo-test version 0.0.0.1
runtest completed at Sun Jan 18 08:29:13 2009

Der Weg, wie ich dorthin komme, um eine Bibliothek namens foo zu testen, ist:

  • Nehmen Sie an, die Quell- und Include-Dateien für die Bibliothek befinden sich in ~/src/foo
  • Erstellen Sie ein Verzeichnis mit dem Namen ~/src/foo/testsuite
  • Schreiben Sie ein Testprogramm namens foo-test.c mit einem main() that
    • verarbeitet Befehlszeilenargumente
    • – gibt eine Eingabeaufforderung aus und befindet sich in einer Schleife, in der “Befehle” verarbeitet werden, in der ich einen Befehl definiere, um jede Funktion in meiner Bibliothek zu testen. Dies ist eine Art Befehlsshell, aber spezifisch für die Bibliothek. Für so etwas wie my_pow würde ich den Befehl so definieren, dass er 2 Argumente nimmt.
    • Schreiben Sie eine Dejagnu-Funktion (die eine weitere Ebene über Expect (http://expect.nist.gov/ ist, die selbst eine Ebene über Tcl (http://www.tcl.tk/) ist) mit der Funktion my_pow, die:
      • nimmt zwei Argumente
      • berechnet das erwartete Ergebnis (in Tcl)
      • sendet “my_pow” an die Konsole
      • analysiert die Ausgabe des Befehls my_pow von foo-test
      • bestimmt, ob das tatsächliche Ergebnis mit dem erwarteten Ergebnis übereinstimmt
      • ruft die entsprechende Dejagnu-Funktion auf (bestanden oder fehlgeschlagen)

Klingt hart, ist es aber nicht. Es dauert eine Weile, um zu entscheiden, wie viel Arbeit in foo-test und wie viel in Tcl zu tun ist. Am Ende verwende ich ziemlich viele Shell-Funktionen (z. B. Bash), um Dinge wie das Kopieren von Dateien in temporäre Verzeichnisse oder das Ansehen der Protokolldateien zu tun, die meine Programme generieren. Also wirst du am Ende gut in all diesen Sachen.

In Bezug auf Referenzen gibt es ein Buch über Expect, von dem ich sagen würde, dass es eine Voraussetzung dafür ist, sich damit zu befassen: http://oreilly.com/catalog/9781565920903/index.html.
Dazwischen und eine Online-Tcl-Befehlsreferenz http://www.tcl.tk/man/tcl8.4/TclCmd/contents.htm und häufig gestellte Fragen (http://www.psg.com/~joem/tcl/faq.html), du bist ziemlich genau da.

Viel Glück.

-DB

1333820cookie-checkBasic Unit Test und C, wie fange ich an?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy