X. Tesztelés és hibakeresés

Teszttechnikák és eszközök

A tesztelés és hibakeresés a tapasztalat szerint a programok fejlesztési idejének legalább a felét veszi igénybe. Ezért is fontos, hogy megismerkedjünk a teszteléssel kapcsolatos alapfogalmakkal, technikákkal és eszközökkel, amelyek a REXX programok fejlesztése közben segítségünkre lehetnek. Elôször is tisztáznunk kell a tesztelés és a hibakeresés fogalmát. A tesztelésen azt a tevékenységet értjük, amely során megpróbáljuk a programunkban esetlegesen megbújó hibákat felfedezni. A hibakeresés során viszont a már (a tesztelés alatt) felfedezett hibák pontos okát kutatjuk a forráskódban. Mivel a két tevékenység alapjaiban különbözik, ezért a felhasználható eszközök tárháza is merôben eltér egymástól. A tesztelés elsôdleges eszköze józan eszünk, finomabban fogalmazva analizáló képességünk. Nagyon fontos, hogy tisztában legyünk a tesztelt program tervezett mûködésével, különben nem leszünk képesek minden fontos dolgot számításba venni. Az is nagyon lényeges, hogy milyen indíttatással kezdünk a munkához. Nagyon sokan a teszteléskor azt akarják bebizonyítani, hogy a programjuk hibátlanul mûködik. Ez sajnos a helytelen hozzáállás. Szinte minden program tartalmaz kisebb nagyobb hibákat, ezért a teszteléskor arra kell összpontosítanunk, hogy megtaláljuk a szinte biztosan létezô hibákat! Az is nagyon fontos, hogy mással is teszteltessük programunkat. Egy program íráskor szinte mindig feltételezünk bizonyos dolgokat, s ezeket a feltételezéseket a tesztelés során sem tudjuk teljesen kiverni fejünkbôl, ami aztán azt eredményezheti, hogy nem fedezzük fel az összes hibát. Ha megvannak a hibák, akkor kezdôdhet a hibák okainak megkeresése (debug). A legtöbb hiba esetében az ok rögtön nyilvánvaló a forráskód alapján. Amikor ez nem így van, akkor a legjobb, ha igénybe vesszük a hibakeresô eszközöket. Ezen eszközök használatával érdemes elôre megismerkedni. A hibakeresés nem egy lelkesítô feladat, s ha még a hibakeresô eszközök használatát is ekkor kell megtanulni, akkor ezzel csak tovább rontjuk lelkiállapotunkat.

Gyakran elôforduló hibaforrások

Nagyon sok féle teszttechnika létezik. Sajnos tanfolyamunk keretébe nem fér bele, hogy ezekrôl részletes áttekintést adjunk, ezért a továbbiakban csak azokat a dolgokat soroljuk fel, amelyeket szinte minden esetben le kell ellenôriznünk, mivel a tapasztalat szerint ezek a hibák leggyakoribb forrásai:

1. Elfogadja a program a megfelelô formában megadott bemeneti adatokat? Próbálkozzunk többféle kombinációval is!

2. Helyes a program kimeneti adata? Megfelelô formában van az adat megjelenítve?

3. Megtagadja a program a helytelen adat bevitelét? Mi történik, amikor egyáltalán nem adunk meg adatot, vagy éppen ellenkezôleg, amikor túl sok adatot viszünk be? Elfogadja a program a betûket is bemenetként, amikor csak számokat lenne szabad?

4. Korrektül mûködik a program a határesetekben is? Határesetek azok az esetek, amikor a mûködési paraméterek a megengedett értékek maximális vagy minimális értékével esnek egybe. Próbálkozzunk a határértékektôl pozitív és negatív irányban csak kicsit eltérô mûködési értékekkel is!

A Trace utasítás

Hibaokok keresésekor nagyon sokat segíthet a Trace utasítás, amellyel nyomon követhetjük a program végrehajtását. A nyomkövetésnek több formája is lehet, amelyek közül a parancs opciójával választhatunk (pl. Trace Result, vagy csak egyszerûen Trace R):

Opció:Jelentés:
AllMinden szerkezetet megjelenít végrehajtás elôtt.
CommandsMinden parancsot megjelenít végrehajtás elôtt. A nem nulla visszatérési értékeket is megmutatja.
ErrorMinden parancsot megjelenít a végrehajtás után, amelynek a végrehajtása hibával végzôdik.
FailureMinden parancsot megjelenít a végrehajtás után, amelynek a végrehajtása nem sikerült (pl. nem létezô, vagy nem végrehajtható parancs).
IntermediatesMinden szerkezetet megjelenít végrehajtás elôtt. A végrehajtás vagy kiértékelés köztes állomásait is megmutatja.
LabelsA végrehajtás során használt címkéket jeleníti meg.
NormalUgyanaz, mint a Failure.
OffA nyomkövetés kikapcsolva. Ez az alapeset.
ResultsMinden szerkezetet megjelenít végrehajtás elôtt. A szerkezetek kiértékelésének eredményét vagy a PULL, PARSE és ARG utasítások végrehajtásának eredményét is kijelzi.

A legtöbbet használt opció a Result. Lássunk erre egy rövid példát. Figyeljük meg azt is, hogy a példaprogramban a Trace parancs opcióját idézôjelek közé tettük, hogy ezzel is elkerüljük az esetleg ugyanolyan név alatt használt változókkal való keveredést!

/* A Trace 'R' használata */
TRACE 'R'
SAY 'Gépelj be három számot!'
PARSE PULL a . b
c = a || b
d = 25 * 3
EXIT

A begépelés és végrehajtás után látnunk kell, hogy a parancsértelmezô kilistázza a végrehajtott szerkezeteket és a kiértékelés után kapott eredményeket:

     3 *-*   Say 'Gépelj be három számot!';
       >>>     "Gépelj be három számot!"
Gépelj be három számot!
     4 *-*   Parse Pull a . b;
1 2 3
       >>>     "1"
       >.>     "2"
       >>>     "3"
     5 *-*   c = a || b;
       >>>     "13"
     6 *-*   d = 25 * 3;
       >>>     "75"
     7 *-*   Exit;

A listázáshoz a REXX ún. elôtagokat használ, amelyek a kilistázott információ értelmezését teszik lehetôvé. Az alábbi táblázatban összefoglaltuk az elôtagokat és azok jelentését:

Elôtag:Jelentés:
*-*Az eredeti szerkezet.
+++A Trace utasítás üzenete. Itt kerül a visszatérési kód is megjelenítésre.
>.>Az elemzéshez használt tölteléktag (.) tartalma.
>>>Kifejezés eredménye, a PARSE által változóhoz rendelt érték vagy függvény visszatérési értéke.
>C>Nyomkövetett összetett változó. (Csak TRACE I esetében használt.)
>F>Nyomkövetett függvényhívás értéke. (Csak TRACE I esetében használt.)
>L>Nyomkövetett szó (literal). (Csak TRACE I esetében használt.)
>O>Nyomkövetett mûvelet eredménye. (Csak TRACE I esetében használt.)
>P>Nyomkövetett elôtag mûvelet eredménye. (Csak TRACE I esetében használt.)
>V>Nyomkövetett változóérték. (Csak TRACE I esetében használt.)

Alapesetben a Trace utasítás fáradhatatlanul listázza a kívánt információt. Gyakran elôfordul azonban, hogy programunkat szerkezetenként szeretnénk végrehajtatni és a szerkezetek között esetleg beavatkozni a futásba, vagy kiegészítô információt kérni. A nyomkövetésnek erre az interaktív formájára is fel van készítve a Trace, és egy, az opció elôtt megadott kérdôjellel jelezhetjük neki, hogy erre vágyunk: TRACE ?I. Amíg a program végrehajtása szünetel, újabb szerkezeteket gépelhetünk be, vagy csak egyszerûen ENTERT-t ütve kérhetjük a soron következô szerkezet végrehajtását. Az = jel begépelésével újra végrehajtathatjuk az elôzô szerkezetet. Az interaktív nyomkövetést bármikor (akár menet közben is) kikapcsolhatjuk a TRACE OFF utasítással. Amennyiben csak néhány, pl. 3 egymás után következô szerkezetet akarunk nyomon követni, akkor a TRACE 3 utasítást kell beépítenünk a programba. Ha negatív számot adunk meg paraméterként, akkor ezzel a nyomkövetést kikapcsolhatjuk a soron következô néhány szerkezetre (TRACE -3 pl. kikapcsolja a követést a következô 3 szerkezetre).

A Signal utasítás

Egy másik hasznos eszköz hibaforrások felkutatására a Signal utasítás. Alkalmazásával ugyanis elérhetô, hogy bizonyos feltételek teljesülése esetén egy, a tesztelt programba beépített speciális programrészlet fusson le, hogy pl. ezáltal is további információhoz jussunk, amely aztán segíthet a hiba okát megtalálni. A Signal utasítás ilyenkor a következô formában használatos: SIGNAL ON/OFF [feltétel]. A lehetséges feltételeket és az azokat elôidézô eseményeket az alábbi táblázatban foglaltuk össze:

Feltétel:Esemény:
ErrorA kiadott parancs hibával ért véget.
FailureA kiadott parancs végrehajtása nem sikerült.
HaltMegpróbálták a programot megszakítani. Nem mûködik, ha a programot külsô rutin futtatása közben szakítják meg!
NotReadyInput/output hiba.
NoValueNem inicializált változó került felhasználásra PARSE VAR szerkezetben.
SyntaxSzintakszis hiba.

Amikor az Error vagy Failure feltételt használjuk, a parancs visszatérési értéke mindig megtalálható az rc változóban. Amikor a Syntax feltétel aktív, akkor pedig a hiba kódszámát tartalmazza az rc. A kódhoz tartozó magyarázatot az ErrorText utasítással írathatjuk ki: SAY ErrorText(rc). Egy másik hasznos elôre definiált változó az sigl, amely annak a szerkezetnek a sorszámát tartalmazza, amelynek a végrehajtása közben beállt a figyelt feltétel. A sorszámhoz tartozó szerkezetet a SourceLine függvénnyel jeleníthetjük meg. Ha paraméter nélkül hívjuk meg a SourceLine-t, akkor a programban lévô sorok számát adja vissza. Az sigl és SourceLine kombinációjával például a figyelt feltétel beállta esetén kiírathatjuk azt a sort, amelynek a végrehajtása okozza a problémát: SAY 'Hiba a(z) 'sigl'. sorban: 'SourceLine(sigl). Itt kell még megemlítenünk a Condition függvényt is, amellyel további információt kaphatunk a beállt feltételrôl. Az alábbi táblázatban összefoglaltuk a függvény lehetséges paramétereit és azok jelentését:

Opció:Eredmény:
ConditionA beállt feltétel neve.
DescriptionA beállt feltétel leírása.
InstructionAz utasítás, amelyik engedélyezte a beállt feltétel figyelését (Signal vagy Call).
StatusA figyelt feltétel státusza (ON, OFF, DELAY).

Ezek után pedig lássunk egy példát a feltételek figyelésére és a Signal használatára. Az alábbi példaprogramban a szintakszis hibákat figyeljük és bekövetkezés esetén (a felhasználó szám helyett betût ad meg) a Syntax címke alatti programrészlet hajtódik végre, amely aztán kiírja a hibás programrészletet. Figyeljük meg, hogy a Trace utasítás után egy üres utasítást (NOP) iktattunk be, amellyel elkerüljük a hiba beállta utáni kilépést a programból.

/* Példa a Signal használatára */
SIGNAL ON Syntax

SAY 'Gépelj be egy nem REXX számot!'
PULL szam
szam = szam + 1
EXIT

Syntax:
	SAY 'Szintaxis hiba 'rc' a következô sorban:' sigl
	SAY ErrorText(rc)
	SAY SourceLine(sigl)
	SAY
	TRACE ?R; NOP;
	EXIT

A leggyakrabban elôforduló hiba a szintakszishiba. Kijavítása általában nem túlságosan bonyolult, azonban kissé hosszadalmas feladat. A hiba bekövetkezése után ugyanis el kell indítani a szövegszerkesztôt, be kell tölteni a programot, meg kell keresni a hibás sort és csak azután történhet meg a javítás. Mivel lehetôség van a hibák programból történô figyelésére, a javítás elôkészítô fázisát (szövegszerkesztô indítása, kód betöltése, hibás sorra pozícionálás) könnyedén automatizálhatjuk. Ehhez azonban elôször le kell kérdezni a programból a futtatott fájl nevét. Erre kiválóan alkalmas a PARSE SOURCE os environ pgmname parancs. OS/2 alatti futtatás esetén az os változó értéke OS/2, az environ értéke COMMAND, a pgmname értéke pedig a programfájl neve lesz. Ezután már csak egy olyan szövegszerkesztôt kell találnunk, amelynek parancssorban adhatjuk meg a betöltendô fájl nevét és a kívánt sorpozíciót. OS/2 alatt erre a célra kiválóan megfelel az EPM:

/* Automatikus szövegszerkesztô indítás */
/* szintaxishiba esetén.		*/
SIGNAL ON Syntax

PARSE PUUL szam 
EXIT

Syntax:
	PARSE SOURCE os environ pgmName
	errorMsg = "'messagebox" ErrorText(rc)"'"
	errorLine = "'" || sigl || "'"
	"EPM" pgmName errorLine errorMsg
	EXIT


Automatikusan indul az EPM szintakszis hibára

A PMREXX program használata

Hasznos segédeszköz lehet még a PMREXX program is, amely segítségével grafikus környezetben futtathatjuk a REXX programokat. A grafikus futtatás a PMREXX [futtatandó program neve] paranccsal történhet. A parancs hatására a REXX program egy PM ablakban fog futni, s az input/output adatok mellett ugyanitt jelenik meg a TRACE információ is, már amennyiben a TRACE be van kapcsolva. A nyomkövetést az ablak menüjében is be- illetve kikapcsolhatjuk. Az ily módon történô futtatásnak az is az elônye, hogy a File/Save utasítások segítségével könnyedén eltárolhatjuk a futtatáskor keletkezett adatokat, valamint a görgetôsáv segítségével kényelmesen nyomon követhetjük a program mûködését.


Grafikus nyomkövetés


REXX GYÍK:

K1. Van-e lehetôség arra, hogy elindítsak egy interaktív hibakövetô szekciót a nélkül, hogy a tesztelt programba be kellene írnom a TRACE utasítást?
V1. Igen. A programindítás elôtt az OS/2 mindig megvizsgálja az RXTRACE környezeti változó értékét. Amikor ON van beállítva, akkor ugyanúgy fogja a REXX értelmezô a programot futtatni, mintha megadtuk volna a TRACE '?R' utasítást. Ha tehát a program futtatása elôtt kiadjuk a SET RXTRACE=ON parancsot, akkor mindenképpen az interaktív hibakövetés szerint fog futni programunk.


Gyakorlatok:

1. Módosítsa az alábbi programot úgy, hogy szintakszis hiba esetén elinduljon a szövegszerkesztô program és kód automatikusan betöltôdjön!

/* Példaprogram */
SAY 'Gépeld be a család és keresztnevedet!'
PARSE PULL csaladnev keresztnev
teljesnev = csaladnev | ',' keresztnev
SAY teljesnev
EXIT

2. Módosítsa az alábbi programot, hogy a Halt szituáció beálltakor a 'USER HALT' üzenet jelenjen meg!

/* Példaprogram */
SAY 'Irj be egy szöveget!'
PARSE PULL szoveg
SAY 'A beírt szöveg: 'szoveg
EXIT

Kádár Zsolt
1998. 04. 12.
[ Elôzô lecke | Következô lecke | Tartalom ]