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

Ú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 tests

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

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.

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.

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.

Ďalšie zdroje