Test-Driven Development
vývoj riadený testami, black-box testing
Videá pre cvičenie
About
Jedna z agilných metodík, ktorá je v praxi bežne používaná, sa nazýva vývoj riadený testami (z ang. test driven development), kedy sa voči známemu rozhraniu najprv napíšu testy a až tak sa vytvára samotná implementácia. Výsledný kód a jeho aktualizácie sú tak neustále kontrolované voči očakávanému správaniu zapísanému v testoch. Ak dôjde zmenou kódu ku chybe, tá je okamžite odhalená pri spustení testov.
Túto metodiku používame aj pri testovaní vašich zadaní v Aréne a na tomto cvičení vám pomôžeme si ju osvojiť.
Objectives
- Porozumieť základom agilnej metodiky vývoja riadeného testami.
- Naučiť sa vytvárať testy v jazyku C pomocou knižnice
assert.h - Vytvoriť vlastné jednotkové (unit) testy funkcií.
Postup
Warm up!
Predtým, ako sa budeme snažiť osvojiť si vývoj riadený testami,
pripravíme si pracovné prostredie. Preto v tomto kroku stiahnete svoj
projekt z git-u a počas cvičenia budete pracovať v priečinku so
zadaním Top Secret (ps1/).
Úloha
Stiahnite, resp. naklonujte si svoj projekt z git-u.
V prípade, ak ste ešte nezačali riešiť toto zadanie, stiahnite si zo
stránky so zadaním Top
Secret kostru projektu a umiestnite ju do priečinku
ps1/ vášho projektu.
Úloha
V priečinku ps1/, ktorý obsahuje zdrojové kódy zadania
Top Secret vytvorte súbor tests_bmp.c a pridajte
ho do projektu na git.
Tento súbor bude obsahovať implementácie testov pre testovanie
funkcií projektu Top Secret. Bude ho však možné preložiť a
spustiť samostatne, preto v ňom vytvorte hlavnú funkciu
main(). V tele funkcie vypíšte na obrazovku dve správy:
Tests started...
All tests passed
Poznámka
Pre úspešné odovzdanie a hodnotenie projektu tento súbor nie je dôležitý. Ak ho teda pridať do projektu zabudnete alebo jednoducho tento krok ignorujete, nebudete za to nijakým spôsobom postihnutí v hodnotení.
Úloha
Do súboru Makefile pridajte nové pravidlo
tests, pomocou ktorého testy preložíte a následne ich po
úspešnom preklade aj spustíte.
Pravidlo bude teda obsahovať dva riadky (príkazy):
- preklad testov
- spustenie testov
V tomto prípade vieme využiť vlastnosť nástroja make, že
ak dôjde pri vykonávaní jedného príkazu k chybe, žiadny ďalší príkaz
nebude vykonaný. To znamená, že ak bude preklad neúspešný, k spusteniu
testov nedôjde.
Do prekladu a teda aj závislostí zahrňte súbory bmp.c a
tests_bmp.c.
Úloha
Overte správnosť svojej implementácie.
Testy spustíte spustením príkazu make a príslušného
pravidla v tvare:
make testsAk ste postupovali správne a neurobili ste žiadnu chybu, na obrazovke sa vypíše:
Tests started...
All tests passed
Úloha
Aktualizujte pravidlo clean súboru Makefile
o zmazanie spustiteľného súboru tests.
Caesar
Bolo by super, keby naše programy vždy fungovali na prvýkrát :-) Keďže to tak v skutočnosti nefunguje, náš kód potrebujeme testovať a ladiť, aby sme odhalili a minimalizovali vzniknuté chyby. Aby sme mohli náš kód testovať a ladiť, musí v prvom rade fungovať! (musí byť spustiteľný) V prvom kroku vytvoríte testy pre implementáciu cézarovej šifry, s ktorou ste sa už stretli, a ktorá tvorí základ pre vytvorenie Vigenèrovej šifry.
Úloha
V súbore bmp.c vytvorte (zatiaľ) prázdnu definíciu
funkcie char* caesar_encrypt().
Funkcia bude mať tieto parametre:
text- vstupný parameter reprezentujúci text, ktorý má byť zakódovanýstep- vstupný parameter reprezentujúci posun v smere doprava
Funkcia bude vracať referenciu na zakódovaný text pomocou Cézarovej šifry.
Úloha
V súbore tests_bmp.c vytvorte funkciu
void test_simple_encrypt(), ktorá otestuje správnosť
implementácie Cézarovej šifry prostredníctvom makra
assert(). Táto funkcia nebude mať žiadne parametre a
nevráti žiadnu hodnotu. Bude reprezentovať jednoduchý test funkcie
caesar_encrypt(), ktorú zavolá s textom na zakódovanie a
tento potom porovná s očakávaným.
Pre použitie makra assert() potrebujete vo svojom kóde
použiť štandardnú knižnicu assert.h.
Pre overenie správnosti fungovania funkcie môžete využiť s výhodou
linuxový nástroj tr. Ak budete chcieť otestovať správanie
vašej funkcie pre posun 5, použitie nástroja tr
bude nasledovné:
tr A-Z F-ZA-EÚloha
Overte funkčnosť riešenia.
Poznámka
Testy by mali byť neúspešné (došlo k výpisu chyby), pretože ste testovali prázdnu funkciu.
Výpis môže vyzerať nasledovne:
Tests started...
Encrypting constant string...
tests: test_bmp.c:19: test_simple_encrypt: Assertion `strcmp("FMTO",result) == 0' failed.
Aborted (core dumped)
Úloha
Rýchlo upravte funkciu caesar_encrypt() tak, aby bol
test úspešný.
Výpis môže vyzerať nasledovne:
Tests started...
Encrypting constant string...
Passed
All tests passed
Úloha
Pridajte do programu zoznam slov a ich šifrovanej podoby, a otestujte
riešenie na všetkých slovách v novej funkcii
void test_caesar_encrypt().
Použiť môžete nasledujúce zoznamy:
const char words[10][10] = { "SEPTEMBER", "THOUSAND", "CASSOVIA", "NEPAL", "EVEREST",
"CAESAR", "ZONE", "YES", "ANDERSON", "KEY" };
const char en_words[10][10] = { "XJUYJRGJW", "YMTZXFSI", "HFXXTANF", "SJUFQ", "JAJWJXY",
"HFJXFW", "ETSJ", "DJX", "FSIJWXTS", "PJD" };Úloha
Overte funkčnosť riešenia.
Poznámka
Testy by mali byť neúspešné (došlo k výpisu chyby), pretože aktuálna implementácia zahŕňa len jednu situáciu.
Výpis môže vyzerať nasledovne:
Tests started...
Encrypting constant string...
Passed
Encrypting set of strings...
tests: test_bmp.c:29: test_caesar_encrypt: Assertion `strcmp(en_words[idx],result) == 0' failed.
Aborted (core dumped)
Úloha
Upravte riešenie cézarovej šifry tak, aby bolo univerzálne a vyhovovalo testom.
Použiť môžete nasledujúcu implementáciu:
char* caesar_encrypt(const char* text, int step){
int len = strlen(text);
char* result = (char*)calloc(len + 1, sizeof(char));
for( int index = 0; index < len; index++ ){
result[index] = (text[index] - 'A' + step) % 26 + 'A';
}
result[len] = '\0';
return result;
}Úloha
Overte funkčnosť riešenia.
Poznámka
Testy by mali byť opäť úspešné (nedošlo k výpisu chyby). Váš test sa však venoval iba obmedzenej skupine slov.
Výpis môže vyzerať nasledovne:
Tests started...
Encrypting constant string...
Passed
Encrypting set of strings...
Passed
All tests passed
Úloha
Vytvorte prázdnu funkciu
char* caesar_decrypt(const char* text, const int step) pre
dešifrovanie a v novej funkcii void test_encrypt_decrypt()
otestujte kombináciu šifrovania a dešifrovania.
Poznámka
Ak dešifrujete zašifrované slovo, výsledkom by malo byť pôvodné slovo.