You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »

Ciele cvičenia

Cvičenie je zamerané na modernú techniku vývoja aplikácii postavenú na báze testovania správania sa funkcii. Tento prístup k vývoju sa nazýva vývoj riadený testami (test driven development), kedy sa voči známemu rozhraniu najprv napíšu testy a až tak sa vytvára samotná implementácia. Po osvojení si učiva, študent dokáže navrhnúť vlastné testy, ktorými je následne schopný testovať vlastné funkcie, ktoré práve vyvíja. Zároveň tento testami riadený vývoj dokáže implementovať v nástroji make a dokáže k nemu vytvoriť adekvátny konfiguračný súbor Makefile.

  • Vývoj riadený testami
  • Implementácia testov s využitím knižnice assert.h
  • Implementácia testov s nástrojom make

Odporúčaná literatúra a dôležité odkazy

[1] KPI-FEI-TUKE: 

[3] KPI-FEI-TUKE: 

[4] Kováč, O.: ZAP - Cvičenie č. 4

[5] Kováč, O.: PROG - Cvičenie č. 3 - Modulárne programovanie


Vývoj riadený testami

Ide o modernú techniku vývoja aplikácii postavenú na báze testovania správania sa funkcii. Tento prístup k vývoju sa nazýva vývoj riadený testami (test driven development -TDD), kedy sa voči známemu rozhraniu najprv napíšu testy a až tak sa vytvára samotná implementácia. Z uvedeného vyplýva, že riešenie zadaného problému nezačína písaním kódu ako sú študenti zvyčajne (nesprávne) zvyknutí, ale začína sa stanovením požadovaných funkcionalít, vstupov a očakávaných výstupov. Pre napĺňanie týchto požiadaviek sa najprv napíše test (testy) a až následne sa napíše kód samotného programu. 

Vývoj programov vo filozofii TDD pozostáva z piatich krokov:

1. Vytvorenie testu

Prvým krokom v TDD je napísanie testu, ktorý bude overovať funkcionalitu vyvíjaného programu. V podstate v tomto kroku sa stanovia požiadavky na funkcionalitu programu. Do istej miery je to veľmi podobné zásadám, ktoré sme sa učili na ZAPku [4]. Je potrebné stanoviť aké budú vstupy a aké budú výstupy vyvíjaných funkcií a programov. Pre zjednodušenie a lepšie porozumenie problematike, budeme ďalej uvažovať iba o funkcionalitách (moduloch - pozri [5]) a nie komplexných programoch.

2. Spustenie testu (prvý krát nesmie prejsť)

Potom ako je napísaný test pre daný modul programu je potrebné napísať kód pre samotný modul. "Prvý krát by tento mal pri testovaní zlyhať". Tomuto kroku treba rozumieť tak, že je potrebné si pripraviť kostru daného modulu, ktorá vráti nejakú preddefinovanú hodnotu alebo nevráti nič a testom tak neprejde. Nesmie sa však stať, že problém nastane pri kompilácii! 

3. Napísanie vlastného kódu a jeho testovanie 

V tomto kroku sa prechádza k vývoju a programovaniu daného modulu a jeho funkcionalít. Tento vyvíjaný kód sa neustále kompiluje a testuje. Ak je test neúspešný je potrebné daný kód upraviť a spustiť ďalší test. Ak vyvinutý modul prejde testom prechádza sa do ďalšieho kroku.

4. Refaktorizácia - postupné vylepšovanie

Kód prechádza testami a robí to čo sa od neho očakáva. V tomto okamihu je možné začať premýšľať nad tým ako by sa daná funkcionalita dala vylepšiť, zefektívniť, rozšíriť a podobne. Stanovia sa teda nové ciele, ktoré treba implementovať do testov. Prechádza sa k poslednému kroku - "uprataniu" 

5. Upratovanie a návrat k bodu 1

Pred návratom k bodu 1 je potrebné vymazať objektové a spustiteľné súbory, ktoré boli v priebehu vývoja skompilované. 




Implementácia testov s využitím knižnice assert.h

Na prvý pohľad sa TDD možno zdá trochu "exoticky" ale test vo svojej podstate je len ďalší program, ktorý obsahuje funkciu main, v ktorej sú volané funkcie testovaného modulu a tieto sú vyhodnocované. Vyhodnocované funkcie by mali mať vstupné parametre ako aj návratové hodnoty. Tento typ funkcii je možné vyhodnocovať pomocou funkcie assert, ktorá sa nachádza v knižnici assert.h. Funkcia assert pokiaľ je jej argument je pravdivý (TRUE) nespraví nič a kód testu pokračuje na ďalší riadok. V prípade, že jej argument bude nepravdivý, vygeneruje sa chyba priamo do  stderr (standard error stream to display error messages and diagnostics). Pokiaľ je tento vykonávaný v nástroji make, dôjde k zastaveniu kompilácie s chybou!

Úloha 1

Vytvorte modul pre základné aritmetické operácie súčet, rozdiel, súčin, podiel, modulo, inverzná hodnota. Tento modul vyvíjajte v súlade s filozofiou TDD! Použite pritom poskytnutú kostru programu.

  • hlavny.c  ktorý obsahuje iba funkciu main si vytvorte tak, aby sa dal skompilovať. V princípe nemusí obsahovať nič okrem return 0.


funkcie.h
/*
  Deklarácie základných matematických operácií pre CV4 z predmetu PROG
*/

int sucet(int, int);  // súčet
int rozdiel(int, int);// rozdiel
int sucin(int, int);  // súčin
int podiel(int, int); // podiel
int modulo(int, int); // výpočet celočíselného zvyšku po delení
int inverz(int, int); // násobenie s -1
funkcie.c
// Definície základných matematických operácií pre CV4 z predmetu PROG

#include "funkcie.h"
int sucet(int a, int b){
  return a + b;
}
int rozdiel(int a, int b){
  return a - b;
}
// Tu majú byť ostatné definície
test_funkcie.c
#include <stdio.h>
#include "funkcie.h"
#include <assert.h>

int main()
{
    printf("\n Testy pre funkcionalitu sucet:");
    assert(sucet(1,1) == 2);             
    printf("\n sucet(1,1) == 2 : PASS");  
    assert(sucet(2,2) == 4);
    printf("\n sucet(2,2) == 4 : PASS");
    assert(sucet(0,2) == 2);
    printf("\n sucet(0,2) == 2 : PASS");
    
    // TU treba dokončiť ostatné testy - aspoň 3 testy na každú funkciu
    
    // Toto je demoštrácia testu ktorý nemá prejsť!
    printf("\n Testy pre funkcionalitu sucet:");
    assert(rozdiel(0,2) == 2); // rozdiel má vrátiť -2, teda je zlý test ale
							   // mohla by byť zle aj funkcia!
    printf("\n sucin(0,2) == 2 : PASS");
    
    printf("\n >>>>> All test PASSED! <<<<< \n");
    return 0;
}
Makefile
CC= gcc
CFLAGS= -Werror -Wall
OUTPUT= PROGRAM
# Všimnime si, že predtým než sa skompiluje hlavny.c je spustený test!
all:  funkcie.o hlavny.o test_funkcie
	./test_funkcie
	gcc $(CFLAGS) hlavny.o funkcie.o -o $(OUTPUT)
	@echo "Skompilovaný celý program"

funkcie.o: funkcie.c
	@gcc -Werror -Wall funkcie.c -c
	@echo "Skompilovane iba funkcie.o"

hlavny.o: hlavny.c
	@$(CC) $(CFLAGS) hlavny.c -c
	@echo "Skompilovane iba hlavny.o"

# Toto je skompilovanie testu pre modul funkcie
test_funkcie: test_funkcie.c funkcie.o
	@$(CC) $(CFLAGS) test_funkcie.c funkcie.o -o test_funkcie

clean:
	rm *.o $(OUTPUT) test_funkcie
	@echo "Vymazalo sa vsetko co bolo potrebne vymazat"



  • No labels