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

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 <img alt=).

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
Zadnja sprememba: sreda, 10. avgust 2011, 10.21