11. diel - Ako testovať programy v C (knižnica assert.h)
V minulej lekciám, Knižnice v jazyku C a C ++ , sme sa venovali tvorbe knižnice. V dnešnom článku si povieme o testovaní programov (častí programov) v céčku.
Spoľahlivosť softvéru je Miera jeho schopnosť vykonávať bezporuchovú činnosť. Spoľahlivosť softvéru sa však zväčša určuje až po dodaní produktu zákazníkovi a to na zaklade rôznych spätných väzieb. To je však príliš neskoro, pretoze na opravu príčinu poruchy musí byť v tajte fázy vynaložené omnoho vyššími nákladmi Ako na ich opravu už počas vývojom softvéru.
Na Vyhodnotenie spoľahlivosti softvéru este pred dodaním zákazníkovi Preto slúžia rôzne modely spoľahlivosti softvéru. Tiete modely sa však Mozu značne líšiť vo svojich ložísk výstupoch. Každý model má určité predpoklady, ktore musia byť splnené, aby bol Výsledok modelovaním čo najpresnejší. Pri výbere modelu sa musí brať do úvahy povaha testovaním, charakteristika softvéru, Ľudský zásah a Spôsob odstraňovaním chýb.
Najprv si prakticky ukážeme, prečo je vhodné všetko testovať. Napíš si jednoduchý program, ktory vyžiadať od užívateľa kladné číslo a potom ho vypíše.
Program
#include <stdio.h> #include <stdlib.h> int main() { printf("Zadajte kladne cislo a stlacte ENTER: "); int cislo; scanf("%d", &cislo); printf("Zadali ste kladne cislo: %d\n", cislo); }
Aké lahko. Lenze ako viem, používateľ je tvor nevyspytateľný a už len pre zábavu zadá napríklad -5.
Testing
Zadajte kladne cislo a stlacte ENTER: -5
Zadali ste kladne cislo: -5
Je jasné, že je to poriadna hlúposti. Predstavte si ale, že je to veľký projekt a ak nebude zadané kladné číslo, celý program sa zrúti ...
Preto si tam doplníme jednoduchý test a predpokladajú, že každý z vás to dokáže na základe doterajších poznatkov nápismi.
#include <stdio.h> #include <stdlib.h> int main() { printf("Zadajte kladne cislo a stlacte ENTER: "); int cislo; scanf("%d", &cislo); /** test **/ if (cislo < 0) { printf("Niekto sa neucil matiku! Koniec programu!\n"); return EXIT_FAILURE; // ukončenie programu } printf("Zadali ste kladne cislo: %d\n", cislo); }
Vyskusam.
Testing
Zadajte kladne cislo a stlacte ENTER: -5
Niekto sa neucil matiku! Koniec programu!
Assert
Dobre, máme to ošetrené, ale v názve článku je spomenuté header Súbor assert.h, takže asi bude Mat testovaním Niečo spoločné.
PRIDAJ si teda do nášho programu #include <assert.h>.
#include <stdio.h> #include <stdlib.h> #include <assert.h>
Táto knižnica obsahuje makro
void assert(int expression);
kde expression je výraz a mozem to hoci premenná Alebo akýkoľvek céčkový výraz. A K je výraz vyhodnotený Ako TRUE, makro nerob nič a program pokračuje Ďalej. A K je výraz vyhodnotený Ako FALSE, zobrazí sa chybové hláseniami a preruší vykonávaním programu.
Tak si to ideme vyskúšať. Namiesto
if (cislo < 0) { printf("Niekto sa neucil matiku! Koniec programu!\n"); return EXIT_FAILURE; // ukončenie programu }
napíšeme
assert(cislo > 0);
Predpokladáme, že vám je jasné, prečo sme dali výraz - číslo je vacsie Ako nula.
Po zadaní čísla 5 je výstup Rovňák Ako v predchádzajúcom prípade, ale po zadaní čísla -5 bude výstup úplne odlišný.
Testing
Zadajte kladne cislo a stlacte ENTER: -5
Testing: /home/libco/cecko/Testing/glass_box_testing.c:12: main: Assertion 'cislo > 0' failed.
Aborted (core dumped)
Vypísala sa cesta k subor, číslo riadku v ktorom je chyba a samotný chybový výraz.
Super. Zoznámili sme sa s na Makro Assert () a mozem si povediete ako ho používať.
Testovanie
Ešte pred tím, Ako si ukážeme skutočnej POUŽITIE tzv. Asercie, pripomenieme si typy chybu s ktorými sa v programoch stretávajú.
V programe sa chyby ukazujte:
- SÚČIASTKY NO prekladu. Tie "sa nám celkom páčia", pretoze nás na ich výskyt celkom presne upozorní prekladača a je otázkou chvíľka ich odstrániť.
- SÚČIASTKY NO výpočtu vždy a okamžite. Tie "sa nám už páčia Menej", pretoze ich výskyt musíme najst sami ladením a to si vyžaduje trochu viac času.
- SÚČIASTKY NO výpočtu po dlhej dobe alebo len niekedy. Tie "sa nám nepáčia Vôbec". Sú to najhorsie chyby. Vtedy program pracuje vacsinou času správne, ale občas, vplyvom (asi) zlý konštalácie hviezd, chybne. Nájdenie tohto druhu chyba je časovo veľmi náročné.
Najprv si povieme o testovaní nazvanom Glass-box Testing.
Prečo glass (sklo)? Pretoze vidíme kód a na jeho zaklade vymýšľame testy, ktore nám ho pomôž doladiť k dokonalosti.
Ja som si v roku 2012 vypracúval úlohy z knižky od Herout (aby som si dokázal, aký som šikovný) a napísal som napríklad takýto program:
/*********************************************** * 12.c ver. 1.0 * Napíšte funkciu strings(char *s1, char *s2, int i);, * ktorá vloží do reťazca s1 od pozície i reťazec s2 a vráti ho. * Využite funkciu strcat(). Použite v programe. * =========================================== * libcosenior, september 2012 ***********************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> char* strings(char *s1, char *s2, int i) { s1[i] = '\0'; // nastaví koniec prvého reťazca podľa zadanej pozície return strcat(s1, s2); // spojí prvý a druhý reťazec a vráti výsledok } int main(void) { int pozicia; char *ret1, *ret2, cislo[3]; // deklarácie pointerov na reťazce, pole char na zadanie čísla if ((ret1 = (char *) malloc(80)) == NULL) { // dynamická alokácia s kontrolou voľnej pamäti printf("Malo pamati!"); return 1; // ukončí beh programu - oznámi počítaču, že program skončil s chybou } if ((ret2 = (char *) malloc(80)) == NULL) { printf("Malo pamati!"); return 1; } printf("Zadaj prvy retazec.\n"); gets(ret1); // zadanie prvého reťazca printf("\nZadaj druhy retazec.\n"); gets(ret2); printf("\nZadaj od ktorej pozicie prveho retazca sa ma vlozit druhy retazec.\n"); gets(cislo); // zadanie reťazca číslo pozicia = atoi(cislo); // skonvertovanie reťazca na celé číslo printf("\n%s\n", strings(ret1, ret2, pozicia)); // výpis návratovej hodnoty volanej funkcie return 0; // ukončí beh programu - oznámi počítaču, že program skončil bez chyby }
Program pracuje perfektne, pokial mu zadávate správne hodnoty.
Testing
Zadaj prvy retazec.
SlonoNosoHroch je zvlastny tvor.
Zadaj druhy retazec.
Koza je domace zvieratko.
Zadaj od ktorej pozicie prveho retazca sa ma vlozit druhy retazec.
5
SlonoKoza je domace zvieratko.
V dobe jeho tvorby som Vôbec nepremýšľal na nad tím, že používateľ je bytosť absolútne nevyspytateľný a okamžite začne zadáva všetko možné, len nie to, čo by vyhovovalo programu.
Tak napríklad Všetky zadania ľan od-Entruje a Výsledok.
Testing
Zadaj prvy retazec.
Zadaj druhy retazec.
Zadaj od ktorej pozicie prveho retazca sa ma vlozit druhy retazec.
Program neurobí nič, pretoze nie je užívateľ-vzdorný (blbú-vzdorný). : O
Tak a teraz nastupuje asercia. Includneme assert.ha vymyslíme, Ako chyby detekovať. Napríklad použijeme výraz: veľkosť reťazca sa nerovná nule
gets(ret1); assert(strlen(ret1) != 0); printf("\nZadaj druhy retazec.\n"); gets(ret2); assert(strlen(ret2) != 0); printf("\nZadaj od ktorej pozicie prveho retazca sa ma vlozit druhy retazec.\n"); gets(cislo); assert(strlen(cislo) != 0); pozicia = atoi(cislo);
Skompilujeme, spustíme a zadáme Enter.
Testing
Zadaj prvy retazec.
Testing: /home/libco/cecko/Testing/glass_box_testing.c:35: main: Assertion 'strlen(ret1) != 0' failed.
Aborted (core dumped)
Vidíme, že asercia funguje a teraz opravíme kód tak, aby to chybu nevyhadzovalo.
while (1) { printf("Zadaj prvy retazec.\n"); gets(ret1); if (strlen(ret1) != 0) break; else { printf("Zadal si len Enter!\nZa trest pockas 5 sekund, kym budes môct zadanie zopakovat!\n"); sleep(5); system("clear"); } } assert(strlen(ret1) != 0); while (1) { printf("Zadaj pdruhy retazec.\n"); gets(ret2); if (strlen(ret2) != 0) break; else { printf("Zadal si len Enter!\nZa trest pockas 5 sekund, kym budes môct zadanie zopakovat!\n"); sleep(5); system("clear"); } } assert(strlen(ret2) != 0); while (1) { printf("\nZadaj od ktorej pozicie prveho retazca sa ma vlozit druhy retazec.\n"); gets(cislo); if (strlen(cislo) != 0) break; else { printf("Zadal si len Enter!\nZa trest pockas 5 sekund, kym budes môct zadanie zopakovat!\n"); sleep(5); system("clear"); } } assert(strlen(cislo) != 0);
Skompilovat -> vyskúšať, ak je problém odstránený -> najst ďalší problém-> Použiť aserciu -> upraviť kód a stále Ďalej, až kým ziadna chyby nenájde.
Ked sa dopracujeme až sem, mozem hoci kód poriadne rozťahané a neprehľadný, jeho časti sa mozu opakovať, program Moze hoci pomalý.
Preto Urobíme ďalšími krokmi:
- Odstránime opakovaný kód (použijeme Funkcie Alebo makrá)
- popíšeme v komentároch Všetky potrebne INFORMÁCIE
- vypneme aserciu
Asercia sa vypína pomocou makra NDEBUG, ktore sa zapne pred includovaním knižnice assert.h takto:
#define NDEBUG // pri zapnutí makra sa vypnú všetky príkazy assert() #include <assert.h>
Moze si povedú: Prečo príkazy Assert () proste len nezmažeme? Preto že ked budeme v Buducnost program upravovať, zase ich zapneme, aby sme mali povodne chyby ošetreniach. Vypnutím asercie ju compilátor Vôbec neberie do úvahy a Preto sa program nespomaľuje dodatočným kódom.
Vacsinou kompilérov Assert odstraňuje v produkčnej verziám kóde (napríklad so zapnutými optimalizáciám Alebo v release verziám). Assert teda slúžia k testovaním programu pred samotným odovzdaním zákazníkovi, nie k validácii užívateľských vstupov. Vo vacsinou prípadovú nechceme, aby celý program Spadola (to urob Assert), ale aby užívateľ upozornil na nesprávny vstup (Alebo stav aplikácie) a dovolil mu chyby opraviť.
Nabudúce si povieme Niečo o test-driven development (TDD) - testami riadenom vývoji.
Na záver prikladám céčkový Súbor assert1a.c.zip, v ktorom som ošetrila POUŽITIE subor Ako na platforme Linux, tak aj na platforme Windows za pomocou príkazového preprocesoru. Spustiteľný subor v archíve nie su, pretoze aby mal Súbor výpovednú hodnotu, treba si ho OTVORIŤ v IDE a potom skompilovat na platforme, ktory používate.
V budúcej lekciám, Ako testovať programy v C (knižnica assert.h) 2. časť , bude pokračovať.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 107x (1.33 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C