Testiranje programov
Testiranje programov (v delu)
Testiranje programov je eno pomembnejših delov programiranja, ki je po krivici velikokrat prezrto. Na tej strani bomo na hitro pregledali osnove testiranja programov s poudarkom na numerični matematiki.V zadnjem času se je razvil celo stil razvoja aplikacij t. i. razvoj osnovan na testih, ki temelji na preskušanju programskih komponent.
Zagotovo so vam že povedali, da naj bi koda vsebovala 1/3 dokumentacije. Veliko manj pa se sliši o tem, da naj bo 1/3 kode posvečena testom.
Splošno o testiranju
Zaenkrat le link na wikipedio
-
enotski testi pridejo prav tudi pri majhnih projektih, kot so domače naloge pri numeriki.
Kako testirati numerične programe
Sintaktična pravilnost
Velikokrat se zgodi, da program ni sintaktično pravilen. V tem primeru se test sploh ne bo izvedel, kajti program se bo predčasno končal zaradi sintaktične napake. Temu se lahko izognemo z uporabo bloka try ... catch.
Numerična enakost
Pri večini testov je treba ugotoviti, ali sta pravilen rezultat in rezultat, ki ga vrne program enaka. Poglejmo si preprosto testno funkcijo, ki preveri, če funkcija sin pravilno izračuna sin(pi).
function rez=test_sin_1(moj_sin) % funkcija preveri, če funkcija moj_sin pravilo računa sinus pi % blok try ... catch smo zaradi jasnosti spustili y=feval(moj_sin, pi); if y==0 printf("%s(pi) je pravilen!\n", moj_sin) rez=1; else printf("%s(pi)=%e je razlicen od 0!\n", moj_sin, y) rez=0; end
Zgornjega testa ne prestane niti vgrajena funkcija sinus
octave:9> test_sin_1('sin') sin(pi)=1.224606e-16 je razlicen od 0! ans = 0
Pri numeriki sta dva rezultata redko povsem enaka. Vedno pride do zaokrožitvenih napak. Zato je enakost smiselno preverjati zgolj na epsilon natančno. Pravi test bi bil
... if abs(y-0)<eps ...
V octavu je eps vgrajena konstanta enaka 2.2204e-16. V posameznih primerih, ko rezultata ne računamo tako natančno, je treba epsilon povečati.
Primerjanje vektorjev in matrik
Namesto abs(x1-x2)<eps pri vektorjih in matrikah uporabimo normo. Najcenejša je neskončna norma, ki za vektorje ni nič drugega kot max(abs(x))
if norm(x1-x2,'inf') ...
Strategije pri testiranju numeričnih programov
Primerjanje z znano rešitvijo
Najbolj preprosta strategija testiranja je primerjanje z znano rešitvijo. Rešitev lahko naredimo pri linearni enačbi A*x=b npr. izračunamo desne strani, pri katerih je x izbrana rešitev.
A=rand(10); x0=ones(10,1); b=A*x0; % resimo sistem x=resi(A,b); % izracunano resitev sistema primerjamo s pravo resitvijo x0 if norm(x-x0,'inf')<eps printf("Resitev je prava!\n") else printf("Resitev je napacna!\n") end
Včasih lahko rešitev poiščemo za kak posebej preprost primer. Newtonovo metodo lahko preiskusimo na funkciji sinus, katere ničle poznamo(vsaj morali bi jih ).
x=newton('sin','cos',3,1e-10,100); if abs(x/pi-round(x/pi))<1e-8 printf("Newton poišče ničlo sinusa.\n") else printf("Newton ni znal poiskati ničle sinusa!\n") end
Primerjanje z vgrajeno funkcijo
Testiranje lastnosti rešitve
Nekatere rešitve lahko preverimo, tako da preverimo, če zadoščajo določenim lastnostim. Tako mora iti npr. interpolacijski polinom skozi vse interpolacijske točke. To je zelo preprosto preveriti
n=length(x); % izracunamo interpolacijski polinom p=polyfit(x,y,n); % p interpolira tocke (x_i, y_i), če je p(x_i)=y_i if norm(y-polyval(p,x),'inf')<eps printf("Polinom p je pravi!") else printf("Polinom p ne interpolira točk!") end
Rešitve enačb
Dobra stara indukcija
Časovna in prostorska zahtevnost
Prostorska zahtevnost
Vedno v naprej alocirajte prostor, ki ga boste potrebovali!!! Če npr. polnimo matriko A dimenzije n*m lahko prostor na začetku alociramo z ukazom zeros
A=zeros(n,m);
Tako že v naprej zagoovimo, da bo dovolj prostora in se izognemu nevšečnosti, da bi po tednu intenzivnega računanja zmanjkalo spomina.
Časomerilec tic/toc
Čas v sekundah lahko v octavu izmerimo z ukozoma tic/toc
octave> tic; for i=1:10^6 sin(i); end; toc ans = 6.6221