Test-Driven Development

vývoj riadený testami, black-box testing

Motivácia

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ť.

Ciele

  1. Porozumieť základom agilnej metodiky vývoja riadeného testami.
  2. Naučiť sa vytvárať testy v jazyku C pomocou knižnice assert.h
  3. Vytvoriť vlastné jednotkové (unit) testy funkcií.

Postup

Krok #1: 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 (ps2/).

Úloha 1.1

Stiahnite, resp. naklonujte si svoj projekt z git-u.

Úloha 1.2

Stiahnite si zo stránky so zadaním Top Secret kostru projektu a umiestnite ju do priečinku ps2/ vášho projektu.

Úloha 1.3

V priečinku ps2/, 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 1.4

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):

  1. preklad testov
  2. 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 1.5

Overte správnosť svojej implementácie.

Testy spustíte spustením príkazu make a príslušného pravidla v tvare:

make tests

Ak ste postupovali správne a neurobili ste žiadnu chybu, na obrazovke sa vypíše:

Tests started...
All tests passed

Úloha 1.6

Aktualizujte pravidlo clean súboru Makefile o zmazanie spustiteľného súboru tests.

Krok #2: 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 2.1

V súbore bmp.c vytvorte (zatiaľ) prázdnu definíciu funkcie char* caesar_encrypt(const char* text, const int step).

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 2.2

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 2.3

Overte funkčnosť riešenia.
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 2.4

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 2.5

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 2.6

Overte funkčnosť riešenia.
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 2.7

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 2.8

Overte funkčnosť riešenia.
Výpis môže vyzerať nasledovne:
Tests started...

Encrypting constant string...
Passed
Encrypting set of strings...
Passed

All tests passed

Úloha 2.9

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.

Diskusia

Upozornenie: Do svojich príspevkov nevkladajte správne riešenia úloh a ani ich od ostatných nežiadajte! Nepoužívajte sprosté slová! Takéto príspevky budú zmazané! Riaďte sa podľa pravidiel etického kódexu.