Warning
This page is located in archive. Go to the latest version of this course pages.

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

courses:b0b36prp:tutorials:testing [2018/10/30 19:52]
courses:b0b36prp:tutorials:testing [2018/10/30 19:52] (current)
Line 1: Line 1:
 +====== Testování HW programů před odevzdáním ======
  
 +Ověření správnosti implementance domácích úkolů není nutné vyloženě realizovat odevzdáváním do BRUTE, tzv. zkoušet odevzdat. Mnohem výhodnější je prostě jen odevzdat správně fungující program, čímž lze ušetřit nejen čas, ale také případný maximální počet uploadů a vyhnout se tak dodatečné penalizaci. Pravděpodbně nejlepším způsobem je detailní inspekce a procházení kódů s tím, že je dobré vědět, co se přesně děje na každém řádku kódu a co se může stát v závislosti na konkrétním vstupu. Taková detailní inspekce však vyžaduje jistou dávku zkušenosti,​ proto jsme pro vás připravili tzv. //​trial/​error//​ možnosti jak ověřit, že program generuje požadovaný výstup.
 +
 +<note tip>​Kromě testování správnosti generovaného výstupu je v případě použití dynamickké alokace v programu výhodné použít program ​ [[http://​valgrind.org/​|valgrind]] ​ pro odhalení nevhodného přístupu ​ nákládání s pamětí viz. [[http://​valgrind.org/​docs/​manual/​quick-start.html| The Valgrind Quick Start Guide]].</​note>​
 +
 +
 +
 +
 +==== Porovnání s testovacími vstupy a výstupy ====
 +První způsobem jak otestovat funkčnost programu je využit přiložených vstupních a výstupních souborů. Například v případě [[courses:​b0b36prp:​hw:​hw01|HW 01 - Načítání vstupu, výpočet a výstup]] vygenerujeme pro vstup ''​data/​pub01.in''​ výstupní soubor ''​my-pub01.out''​ a porovnáme s přiloženým souborem ​
 +
 +<​code>​
 +$ ./​b0b36prp-hw01 < data/​pub01.in > my-pub01.out
 +$ diff data/​pub01.out my-pub01.out
 +2c2
 +< Sestnactkova soustava: b 18
 +---
 +> Sestnactkova sostava: b 18
 +</​code>​
 +kde si můžeme všimnout překlapu //sostava// místo //​soustava//​. Případně můžeme použít program ''​vimdiff''​ nebo jiný tzv. //​rozdílovač//​. Alternativně,​ zejména pak pro výstupy s bílými znaky může být výhodné zobrazit výstup ve hexadecimálním tvaru příkazem ''​hexdump'',​ např.
 +<​code>​
 +$ hexdump -C my-pub01.out
 +</​code>​
 +který můžeme též uložit do soubory a následně porovnat například již zmiňovaným ''​vimdiff''​.
 +
 +<​code>​
 +$ hexdump -C my-pub01.out >​my-pub01.out.hex
 +$ hexdump -C data/​pub01.out >​pub01.out.hex
 +$ vimdiff pub01.out.hex my-pub01.out.hex
 +</​code>​
 +{{:​courses:​b0b36prp:​tutorials:​vimdiff.png?​800|}}
 +
 +==== Generování náhodného vstupu a referečního řešení ====
 +
 +Další možností je využít přiloženého programu pro generování náhodných zadání (vstupních souborů), který zároveň funguje také jako refereční řešení. Například pro [[courses:​b0b36prp:​hw:​hw02|HW 02 - První cyklus]] se generátor/​referenční řešení nachází v binárním souboru ''​b0b36prp-hw02-genref'',​ který je sestaven pro prostředí v počítačových učebnách, tj.
 +<​code>​
 +$ file b0b36prp-hw02-genref ​
 +b0b36prp-hw02-genref:​ ELF 64-bit LSB executable, x86-64, version 1 (GNU/​Linux),​ statically linked, for GNU/Linux 3.2.0, stripped
 +</​code>​
 +
 +Program má minimalistické rozhraní a nápovědu lze vyvolat přepínačem ''​-h'',​ např. ''​./​b0b36prp-hw02-genref -h''​
 +<​code>​
 +$ ./​b0b36prp-hw02-genref -h
 +Generator and reference solution of the HW02
 +Version $Id: main.c 418 2018-10-09 14:08:01Z vanapet1 $
 +Usage:
 +./​b0b36prp-hw02-genref [-generate] [-h]
 +Generator is enabled by -generate argument and produce a random instance of the HW02
 +Otherwise a reference solution expect the input and produced the output as it is required in the assigment of the HW02
 +-h produce this help message
 +
 +In a case of any troubles report them to the teachers together with the '​Version $Id: main.c 418 2018-10-09 14:08:01Z vanapet1 $'
 +</​code>​
 +
 +Ve vychozím použití funguje jako refereční řešení očekávájící vstup na ''​stdin''​ a generuje výstup na ''​stdout'',​ např.
 +<​code>​
 +$ ./​b0b36prp-hw02-genref <​data/​pub01.in >​pub01-ref.out
 +$ diff data/​pub01.out pub01-ref.out ​                  
 +</​code>​
 +kdy je generovaný výstup shodný s přiloženým výstupním souborem ''​data/​pub01.out''​.
 +
 +V případě uvedení argument ''​-generate''​ program vypíše na ''​stdout''​ náhodný vstup
 +
 +<​code>​
 +$ ./​b0b36prp-hw02-genref -generate > my01.in
 +Generate random instance for HW02
 +$ cat my01.in ​
 +9999  -9999  -2242 -675   21
 +</​code>​
 +pro který lze následně vytvořit refereční výstup
 +
 +<​code>​
 +$ ./​b0b36prp-hw02-genref <my01.in >​my02.out ​
 +$ cat my02.out ​
 +9999, -9999, -2242, -675, 210
 +Pocet cisel: 5
 +Pocet kladnych: 2
 +Pocet zapornych: 3
 +Procento kladnych: 40.00
 +Procento zapornych: 60.00
 +Pocet sudych: 2
 +Pocet lichych: 3
 +Procento sudych: 40.00
 +Procento lichych: 60.00
 +Prumer: -541.40
 +Maximum: 9999
 +Minimum: -9999
 +</​code>​
 +který lze použít pro ověření funkčnosti vlastní implementace způsobem uvedeným výše.
 +
 +V případě domácího úkolu, který má povinnou a volitelnou část, lze generátor přeponout do režimu generování vstupu pro volitelné zadání přepínačem ''​-optional''​. Například v případě [[courses:​b0b36prp:​hw:​hw03|HW 03 - Kreslení (ASCII art)]] se standardní zadání generuje ​
 +<​code>​
 +$ ./​b0b36prp-hw03-genref -generate
 +Generate random instance for HW03
 +31 36
 +</​code>​
 +a vstup pro volitelné zadání
 +<​code>​
 +$ ./​b0b36prp-hw03-genref -generate -optional
 +Generate random instance for HW03
 +33 33 3
 +</​code>​
 +V těchto případech je náhodně generovaný vstup vypsán na ''​stdout''​ a "​Generate random instance for HW03" je vypsána na ''​stderr''​.
 +<note important>​Pamatujte,​ že generátor zpravidla vytváří validní vstupy, váš program však musí správně reagovat na špatné vstupy, které můžete například vytvořit editací generovaných vstupních souborů.</​note>​
 +==== Skriptování ====
 +
 +Náhodně generovanými vstupy sice nelze zaručit plné otestování aplikace, ale lze výrazně zvýšit odhalení chyby. Ručně generovat jednotky nebo desítky či stovky náhodných vstupů je zbytečně pracné a můžeme použít krátkého programu pro příkazový interpret. V archivu je tak vedle generátoru/​referečního řešení přiložen skript ''​generate_solution.sh'',​ který např. vytvoří čtyři vstupní soubory a k tomu odpovídající referenční řešení:
 +
 +<code bash>
 +$ cat 
 +#!/bin/sh
 +
 +HW=02
 +PROGRAM=./​b0b36prp-hw$HW-genref
 +
 +mkdir -p files
 +for i in `seq 1 4`
 +do
 +   ​PROBLEM=files/​test$i
 +   echo "​Generate random input '​$PROBLEM.in'"​
 +   ​$PROGRAM -generate > $PROBLEM.in 2>/​dev/​null
 +   echo "Solve '​$PROBLEM.in'​ and store the reference solution to '​$PROBLEM.out'"​
 +   ​$PROGRAM < $PROBLEM.in > $PROBLEM.out 2>​$PROBLEM.err
 +done
 +</​code>​
 +kde pro definici čtyř vstupů je použit program ''​seq'',​ který na ''​stdout''​ vypíše posloupnost v rozsahu jeho argumentů.
 +
 +Skriptu lze podobným způsobem využít pro dávkové otestování vlastního programu a porovnání s referenčním řešení, viz [[https://​cs.wikibooks.org/​wiki/​Skriptov%C3%A1n%C3%AD_v_Bournov%C4%9B_shellu|Skriptování v Bournově shellu]]
 +
 +<note important>​Testování implementace na dodaných nebo náhodně vytvořených vstupech nepředstavuje úplný a zaručený způsob ověření správnosti implementance. Je však způsobem relativně rychle a přímočaře objevit chyby způsobené přehlednutím nebo nepozorností. Pamatujete, že při řešení praktických úloh zpravidla nebudete mít k dispozici refereční řešení a je plně na programátorovi,​ že sám odhalí případné chyby. Proto berte generátory a refereční řešení jako doplněk, nikoliv jako garanci správnosti řešení.</​note>​
 +
 +
 +==== Testování implementace v dynamicky linkované knihovně ====
 +
 +Další z možností jak lze implementaci úkolu testovat je přímé použití implementovaných funkcí v nějaké programu. Sestavení takového testovacího programu s novou implementací vyžaduje zdrojové kódy nebo alespoň přeložené soubory (//object file - .o//). V případě, že chceme pouze změnit implementaci konkrétních funkci aniž bychom měnili rozhraní, můžeme využít mechanismu dynamicky linkovaných knihoven, kdy se konkrétní implementace linkuje k programu až při jeho spuštění. Binární testovací program tak zůstává identický a jediné co měníme je příslušná dynamická knihovna, která zachovává stejné rozhraní definované v příslušném hlavičkovém souboru. ​
 +
 +V úloze [[courses:​b0b36prp:​hw:​hw08|HW 08 - Kruhová fronta v poli]] je cílem implementovat sadu funkcí pro práci s kruhovou frontou a to dle rozhraní předepsaného v ''​queue.h'',​ proto se přímo nabízí sestavit z implementace ''​queue.c''​ dynamickou knihovnu, což lze realizovat například volámím
 +
 +<​code>​
 +clang -fPIC -shared queue.c -o libqueue.so
 +</​code>​
 +které je součástí přiloženého ''​Makefile''​.
 +
 +A pak již stačí spustit testovací program ''​b0b36prp-hw08-test'',​ který hledá dynamickou knihovnu v aktuálním pracovním adresáři, což lze například ověřit ​
 +<​code>​
 +$ ldd b0b36prp-hw08-test
 +b0b36prp-hw08-test:​
 + libqueue.so => ./​libqueue.so (0x2c423000)
 + libc.so.7 => /​lib/​libc.so.7 (0x2c624000)
 +</​code>​
 +
 +Toho je docíleno linkováním ​
 +<​code>​
 +clang b0b36prp-hw08-test.c queue.c -o b0b36prp-hw08-test -L. -Wl,​-rpath=. -lqueue
 +</​code>​
 +kde ''​-lqueue''​ specifikuje knihovnu a ''​-L.''​ cestu, kde se má knihovna hledat pro účely sestavení programy. Pro účely linkování dynamické knihovny při spuštění programu je nutné dále instruovat //linker// specifikací ''​rpath'',​ což je parameter linkeru, které se uvádějí za ''​-Wl,''​.
 +
 +<note tip>
 +Kromě ''​rpath''​ lze také explictině specifikovat dynamickou knihovnu prostřednictví proměnné prostředí LD_LIBRARY_PATH,​ kterou lze předefinovat aktuální systémové nastavení, jež lze přirozeně také upravit dle potřeb, více viz např. [[https://​www.cprogramming.com/​tutorial/​shared-libraries-linux-gcc.html|Shared libraries with GCC on Linux]].
 +</​note>​
 +
 +Po úspěšném sestavaní dynamické knihovny vlastní implementace lze spustit testovací program např. ​
 +
 +<​code>​
 +$ ./​b0b36prp-hw08-test ​
 +Basic test ........... PASSED
 +Overflow test ........ PASSED
 +Multiple queues test . PASSED
 +Reallocation test .... PASSED
 +All tests passed
 +
 +</​code>​
 +
 +Nebo v případě dodatečného testování funkcionality volitelného zadání jako
 +<​code>​
 +$ ./​b0b36prp-hw08-test -prp-optional
 +Basic test ........... PASSED
 +Overflow test ........ PASSED
 +Multiple queues test . PASSED
 +Reallocation test .... PASSED
 +Shrink test .......... PASSED
 +All tests passed
 +</​code>​
courses/b0b36prp/tutorials/testing.txt · Last modified: 2018/10/30 19:52 by faiglj