Guten morgen,
ich soll unittests schreiben, habe aber bei einer bedingung ein Problem.
Folgende funktion:
1
voidhandleReceive(void)
2
{
3
uint8_t*header;
4
header=NULL;
5
6
removeReceive(cid_b,&(header),&(length),&is_valid);// hier wird header gesetzt
7
if(NULL!=header)
8
{
9
data=header;
10
MessageReceive(data,length);// Diese Funktion ist gemockt
11
12
if(NULL!=data)
13
{
14
// mache etwas
15
}
16
else
17
{
18
// mache etwas anderes
19
}
20
}
21
}
Mein Problem ist die bedingung
if(NULL != data)
hier bekomme ich es nicht hin, dass data=NULL ist, da es ja quasi vorher
schon abgefragt worden ist (NULL != header und data = header).
Jetzt habe ich versucht data in der Funktion MessageReceive zu löschen
1
voidmockMessageReceive(uint8*buffer,uint16lenght)
2
{
3
// buffer= NULL;
4
5
// delete buffer;
6
7
// uint8 *pointer;
8
// pointer = NULL;
9
// buffer = pointer;
10
11
free(buffer);
12
13
printf("buffer: %p\r\n",&buffer);
14
}
Allerdings bekomme ihc es nicht hin buffer zu löschen, bzw. buffer auf
NULL zu setzen.
Das geht auch so nicht. (Außer data wäre eine globale Variable und das
ist hoffentlich nicht der Fall)
Ansonsten mach dir die Übergabe Typen (Call-by-Value und
Call-by-Reference) klar.
Dann siehst du, dass die Abfrage
Wie sieht die Signatur des Originals MessageReceive() aus?
Wenn das die gleiche ist wie bei mockMessageReceive(), dann kann die
Funktion/Methode buffer bzw. data nicht geändert zurückgeben. Damit ist
Test if(NULL != data ) überflüssig.
Wo ist data definiert? Globale Variable?
So wie das programmiert ist, könnte die Verzweigung Toter Code sein
(wenn die globale Variable nicht durch andere Codeteile verändert werden
kann).
Für toten Code kann man keine Tests durchlaufen lassen. Das geht nur per
Analyse.
Das ist ein Dilemma. Machst Du die Frage weg, wird das bei der nächsten
Änderung durchgehen.
Also brauchst Du statt if ein Konstrukt, dass als Zusicherung aktiv
bleibt aber nicht als zu durchlaufender Zweig zählt.
Eine Art assert, dass eine Warnung verursacht, wenn es auftreten kann.
Den Code zu durchlöchern ist hingegen kontraproduktiv.
Hannes J. schrieb:> Damit ist> Test if(NULL != data ) überflüssig.
Und daher ist es auch irgendwie sinnfrei, darauf zu zu unit-testen.
Chandler B. schrieb:> free(buffer);
Da sitzt das Problem. data kann zwar nicht NULL werden, aber auf einen
nicht mehr gültigen Datenblock zeigen.
Oliver
Chandler B. schrieb:> MessageReceive(data, length); // Diese Funktion ist gemockt
na, dann mock halt per #define und setze data auf 0.
aber wie gesagt, befasse Dich lieber mit statischer Code-Analyse statt
"100% getestet, also alles OK".
Dass ein Codepfad tot ist und damit sinnlos und nicht testbar, ist das
Ergebnis deines Tests.
Dieser Pfad kann also in der nächsten Version des Codes entfernt werden.
MaWin schrieb:> Dieser Pfad kann also in der nächsten Version des Codes entfernt werden.
Wie stelle ich sicher, dass dieser Zweig auch "tot" bleibt?
Also wie ist das Konstrukt einer Sicherheitsabfrage, die nie zuschlagen
soll?
doppelt hält besser schrieb:> Man kann doch
Man kann sicherlich alles mögliche, aber im Code oben steht halt die
Funktion
Chandler B. schrieb:> MessageReceive(data, length); // Diese Funktion ist gemockt
und die kann data nicht verändert.
Die einzige Möglichkeit, data auf NULL zu bekommen, wäre über einen
amoklaufenden Parallel-Thread, der den Datenbereich überschreibt. Ob man
daraf testen will oder gar muß, muß der TO selber wissen.
Oliver
Chandler B. schrieb:> uint8_t *header;> header = NULL;> removeReceive(cid_b, &(header), &(length), &is_valid); // hier wird> header gesetzt
Da wird ja der Doppelzeiger benutzt.
Man muss halt auch bei der zweiten Funktion genauso arbeiten.
die Frage ist ja sowieso woher diese Variable "data" kommt. Vielleicht
ist die Variable ja sogar global.
A. S. schrieb:> Wie stelle ich sicher, dass dieser Zweig auch "tot" bleibt?
assert()
Wenn der echte Code allerdings nicht deutlich komplexer ist, als der
gezeigte Code, sehe ich keinen Sinn in dieser Abfrage.
Sogar ganz im Gegenteil. Die zusätzliche Abfrage verkompliziert den
Code. Die Lesbarkeit wird verschlechtert und somit wird die
Fehleranfälligheit erhöht.
Ich würde den Pfad also ersatzlos streichen oder höchstens durch ein
assert() ersetzen.