RAM Variablen in bestimmten Bereich linken



  • Hallo,

    ich schreibe mit Eclipse und MinGW ein kleines C-Programm, um ein weiteres C-Modul zu testen. Dazu compiliere ich mein Testmodul einfach mit und schreibe meine Testroutinen in die main-Funktion. Nun habe ich eine Reihe Testfälle, die möglichst immer die gleiche Ausgangssituation vorfinden sollen. Der RAM von meinem Testmodul beinhaltet ja noch die Werte vom vorherigen Test.
    Nun hatte ich die Idee, mein Test-Modul einfach in einen separaten RAM-Bereich zu linken und diesen vor jedem Testcase neu zu initialisieren. Aber wie mach ich das? Also wie sage ich dem Linker, dass er den RAM von bestimmten C-Dateien in einen separaten Bereich legen soll und wie komme ich an diesen später heran?

    Gruß, Heimchen



  • Der übliche Ansatz sind die setUp()- und tearDown()-Methoden, die es in den meisten Unit-Test-Frameworks gibt. Z.B. für CppUnit. Die werden vor jedem einzelnen Testfall aufgerufen und stellen immer dieselbe Initialumgebung her.

    Linker und Speichersegmente sind hier jedenfalls fehl am Platz.



  • Ok, vielleicht ist meine Herangehensweise nicht ganz ausgereift. Gibt es denn für C-Module auch ein solches Framework?





  • Kannst du mir davon eins empfehlen? Ich will Code testen, der später auf einem Microcontroller laufen soll.



  • Google Test fand ich ganz gut. Integriert sich auch mit dem Test-Runner von Eclipse.



  • Sehe gerade, dass Google Test wohl C++-spezifisch ist.



  • Hab inzwischen auch CUnit und CuTest mal angeschaut und lese mir grad die Beschreibung von Check durch. Allerdings habe ich meine Funktion noch nicht gefunden.
    Ich sehe das Problem, dass mein zu testendes Modul ja Teil des Testprogramms ist und ich es nicht wie eine Klasse für jeden Test neu instanzieren kann. Dieses Modul definiert intern static Variablen, die das Verhalten beeinflussen. An diese komm ich aus meinem Test-Code nicht heran (da static) um sie zu manipulieren. So habe ich aktuell keine Möglichkeit, den "frisch compilierten Zustand" meines Modells für jeden Test Run wiederherzustellen. Es sei denn, ich würde den zu testenden Code anpassen, was ich nicht will. Ich hab auch keine Idee, wie sowas in C gehen sollte, außer ich würde meine Idee mit der Linker-Option umsetzen.

    Also wenn jemand weiß, wie ich zu dem gewünschten Ergebnis komme, wär ich sehr dankbar.



  • heimchen schrieb:

    Dieses Modul definiert intern static Variablen, die das Verhalten beeinflussen. An diese komm ich aus meinem Test-Code nicht heran (da static) um sie zu manipulieren. So habe ich aktuell keine Möglichkeit, den "frisch compilierten Zustand" meines Modells für jeden Test Run wiederherzustellen. Es sei denn, ich würde den zu testenden Code anpassen, was ich nicht will.

    ...du aber solltest. Wenn dein Code nicht testbar ist, ist das schlechtes Design. Mach eine Initialisierungsfunktion statt statischer Variablen.



  • Genau das ist das Problem: es gibt eine Initialisierungsfunktion, die den Initialisierungsstatus in einer statischen Variable speichert. Ich habe aber einige Tests, die das nicht initialisierte Modul testen. Ich müsste also nach einer Initialisierung wieder den nicht initialisierten Zustand herstellen.
    Das würde ich auf dem µC über ein Reset tun, beim Testen würde ich einfach die von der Initialisierung betroffenen Variablen zurücksetzten - wenn ich denn dran käme. Den Reset bzw. eine Neuinitialisierung des RAMs würde ich aber besser finden, da das dann tatsächlich dem Verhalten auf dem µC entspricht.



  • heimchen schrieb:

    Genau das ist das Problem: es gibt eine Initialisierungsfunktion, die den Initialisierungsstatus in einer statischen Variable speichert. Ich habe aber einige Tests, die das nicht initialisierte Modul testen.

    Warum muß das nicht initialisierte Modul getestet werden? Sollte man es nicht vor dem Benutzen initialisieren?

    heimchen schrieb:

    Das würde ich auf dem µC über ein Reset tun, beim Testen würde ich einfach die von der Initialisierung betroffenen Variablen zurücksetzten - wenn ich denn dran käme. Den Reset bzw. eine Neuinitialisierung des RAMs würde ich aber besser finden, da das dann tatsächlich dem Verhalten auf dem µC entspricht.

    Wenn du das wirklich so machen willst, würde ich einen zweiten Prozeß als Test-Runner nehmen, der deinen Testprozeß so oft neustartet, wie eine (De-)Initialisierung erforderlich ist. Aber schön ist es nicht.



  • Hi,

    an so etwas hab ich auch schon gedacht. Also dass z.B. mein Programm anhand eines Parameters erkennt, welchen Testlauf es durchführen soll und bei keinem alle Testläufe durchführt. Die Frage ist nur, wie bekomm ich das hin? Ist so etwas vielleicht in so einem Framework schon vorgesehen? Wie bekomm ich hinterher die Ergebnisse wieder zusammen?

    Zwingend notwendig ist das insofern, dass ich zwei Testfälle für den Komponentenstatus haben. Der eine prüft, ob der bei der Initialisierung korekt weiterspringt, der andere, dass die Interfaces auch nur dann funktionieren, wenn das Modul korrekt initialisiert wurde.



  • heimchen schrieb:

    an so etwas hab ich auch schon gedacht. Also dass z.B. mein Programm anhand eines Parameters erkennt, welchen Testlauf es durchführen soll und bei keinem alle Testläufe durchführt. Die Frage ist nur, wie bekomm ich das hin? Ist so etwas vielleicht in so einem Framework schon vorgesehen? Wie bekomm ich hinterher die Ergebnisse wieder zusammen?

    Ob das vorgesehen ist, weiß ich nicht, aber die erforderliche Kommunikation ist ja wirklich minimal: ein Auswahlparameter für den jeweiligen Testfall, ein Rückgabewert ("Exit-Code") für Erfolg oder Mißerfolg. Fehlermeldungen mit den Details nach STDERR. Wenn dein Test-Runner ein GUI hat, kannst du ja STDERR parsen.

    heimchen schrieb:

    Zwingend notwendig ist das insofern, dass ich zwei Testfälle für den Komponentenstatus haben. Der eine prüft, ob der bei der Initialisierung korekt weiterspringt, der andere, dass die Interfaces auch nur dann funktionieren, wenn das Modul korrekt initialisiert wurde.

    Das sehe ich ein, und dann ist es auf jeden Fall besser, mit getrennten Prozessen zu testen als irgendwas mit Segmenten zu tricksen, sonst ist das auch noch fehlerbehaftet und du mußt auch dafür Tests schreiben.



  • audacia schrieb:

    heimchen schrieb:

    an so etwas hab ich auch schon gedacht. Also dass z.B. mein Programm anhand eines Parameters erkennt, welchen Testlauf es durchführen soll und bei keinem alle Testläufe durchführt. Die Frage ist nur, wie bekomm ich das hin? Ist so etwas vielleicht in so einem Framework schon vorgesehen? Wie bekomm ich hinterher die Ergebnisse wieder zusammen?

    Ob das vorgesehen ist, weiß ich nicht, aber die erforderliche Kommunikation ist ja wirklich minimal: ein Auswahlparameter für den jeweiligen Testfall, ein Rückgabewert ("Exit-Code") für Erfolg oder Mißerfolg. Fehlermeldungen mit den Details nach STDERR. Wenn dein Test-Runner ein GUI hat, kannst du ja STDERR parsen.

    Ja, so in etwa hatte ich das auch mal probiert und das wäre auch so ziemlich das, was ich haben möchte. Bei meinem Test-Framework (CuTest) ist es nun aber so, dass das Testergebnis in der Test-Casestruktur steht. Darin steht, ob er ausgeführt wurde, ob er erfolgreich war und ein STring mit der Fehlermeldung. Daraus kann ich mir dann nämlich einen schönen Report ausgeben lassen. Das kann ich zwar auch für jeden Testfall einzeln, sieht nur nicht so schön aus. Darum hatte ich daran gedacht, die gesamte TestCase-Struktur möglichst als Referenz zu übergeben, sodass das Ergebnis des Subprozesses wieder in meiner alten Struktur landet.


Anmelden zum Antworten