Test-Driven Development

vývoj riadený testami, black-box testing

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 1.1

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 1.2

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 1.3

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 1.4

Overte správnosť svojej implementácie.

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

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

Tests started...
All tests passed

Úloha 1.5

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

Úloha 2.3

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

Úloha 2.6

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 2.7

Upravte riešenie cézarovej šifry tak, aby bolo univerzálne a vyhovovalo testom.

Použiť môžete nasledujúcu implementáciu:

Úloha 2.8

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

Ďalšie zdroje