Tesztelés: alapok¶
A tesztelés nem azzal kezdődik, hogy elkezdem kipróbálni a rendszert. Legalábbis, ha jól akarjuk csinálni, akkor nem. Előtte mindig meg kell tervezni a teszteket. A teszteket black-box módon kell megtervezni (lesz majd más is, de nem most), azaz úgy, hogy az implementációból semmit sem látunk. Vagyis csak a specifikáció, elvárt viselkedés alapján kell meghatározni az inputokat és a hozzájuk tartozó elvárt outputokat.
A gyakorlathoz letölthető csomagban van (többek között) egy nak.c
program (a forráskódját NE nézzétek meg!)
Ez az n alatt k számítást valósítja meg, példaként ezt a programot fogjuk tesztelni nagyon egyszerű módon:
a teszt inputot és elvárt outputot egy-egy test-nak.??.in
és test-nak.??.exp
fájlban tároljuk,
a program tesztelésekor az előbbit ráirányítjuk a program standart inputjára, a kimenetet átirányítjuk egy test-nak.??.out
nevű fájlba,
majd a megfelelő .out
és .exp
fájlok tartalmát összehasonlítjuk;
ha egyezik, akkor a teszt PASS, ha nem, akkor FAIL minősítést kap.
A csomagban található Makefile test
target-je pont ezt fogja csinálni (és linux alatt még szépen színezi is).
n alatt k program követelményei
Az n alatt k értékét számoló programmal szemben támasztott követelmények:
- A program két egész számot vár n és k sorrendben, majd kiszámolja az n alatt k értéket ezekkel a számokkal,
és egy sorban
#n alatt #k = #nak
formában kiírja a konzolra (ahol#n
és#k
a megadott n és k értékek decimális alakban,#nak
pedig a kiszámolt n alatt k érték szintén decimális alakban). - Ha az adott paraméterekre az n alatt k értéke nem értelmezett, akkor az
#n alatt #k nem értelmezett!
szöveg kerül kiíratásra. - Adathiba esetén (pl. ha a program nem két egész számot kap paraméterül) a kimenet a
Hibás adat!
szöveg. - A programnak 64 biten észszerűen számolható értékekre kell működnie, ezért 62-nél nagyobb n értékekre nem értelmezett.
Teszttechnikák¶
A tesztek célja, hogy a szoftverben hibát találjanak. Ha ezt "csak úgy" csináljuk, akkor valószínűleg sok felesleges tesztet fogunk végezni, és nem fogunk minden lényeges aspektust érinteni. Van pár olyan alapvető elv/technika, melyek segítségével viszonylag könnyen tudunk viszonylag alapos teszteket készíteni.
Ekvivalenciapartíciók¶
Az elv: ha a programnak különféle működési módjai vannak, minden működési módot teszteljünk (pontosan) egy tesztesettel. Ha például az n alatt k programot teszteljük, n alatt 0-ra, n alatt n-re (ezek a "bázisesetek") és nem 0 alatt nem 0-ra is, valamint érvénytelen kombináció(k)ra: n alatt n+x, és ide igazából akármi is jöhetne. Lehet, hogy a megvalósítás nem indokolja ezt a felosztást, de a feladat igen!
Ekvivalencia partícionálással előálló tesztek (példa):
01: n alatt 0 eset: 5 alatt 0
Az input:
1 |
|
1 |
|
02: n alatt n eset: 5 alatt 5
Az input:
1 |
|
1 |
|
03: nem 0 alatt nem 0 eset: 5 alatt 3
Az input:
1 |
|
1 |
|
04: n alatt n+x eset: 3 alatt 5
Az input:
1 |
|
1 |
|
05: invalid input eset: ''three'' alatt ''two''
Az input:
1 |
|
1 |
|
Határérték-analízis¶
Ha a program működése tartományokon, intervallumokon alapszik, akkor érdemes az intervallumok határértékeit és azok "külső" szomszédait is ellenőrízni. Szomszédos intervallumoknál lehet, hogy a "külső" szomszéd a szomszédos intervallum határértéke lesz. Ha például az n alatt k programot teszteljük azzal a kikötéssel, hogy n = 62 és az alatt kell működnie, különben nem értelmezett, akkor ugye az n ∈ [0, 62] intervallumról beszélünk, vagyis az n = 0 és n = 62 határértékek, az n = -1 és n = 63 pedig "külső" szomszédok. Ezek mellé kell okosan k-t választani.
Határérték-analízissel előálló, az n elfogadott értékét tesztelő tesztek (példa):
06: alsó végpont külső szomszédja: -1 alatt 5
A k értéke itt szinte lényegtelen (amíg egész szám).
Az input:
1 |
|
1 |
|
07: alsó végpont: 0 alatt 0
A k értéke itt érvényes kell, hogy legyen.
Az input:
1 |
|
1 |
|
08: felső végpont: 62 alatt 31
A k megint csak bármi lehetne (persze 0 és n között), de mivel az n alatt n/2 adja a legnagyobb értéket, így ezt választjuk: ha erre jól számol, nagy baj nem lehet.
Az input:
1 |
|
1 |
|
Ha kombináljuk a technikákat, akkor ezzel kiváltjuk a 03-as tesztesetet.
09: felső végpont külső szomszédja: 63 alatt 2
Itt a k értéke megint csak majdnem mindegy: azért legyen jó n-hez, mert nem az eleve rossz k érték kezelésére vagyunk kíváncsiak.
Az input:
1 |
|
1 |
|
További lehetséges példák
Határérték-analízist lehet a k értékére is alkalmazni, amely esetben k ∈ [0, n] miatt a k=0 és k=n határértékekről, és a k=1 és k=n+1 "külső" szomszédokról beszélünk. Itt nyilván az n értékét is meg kell majd választani valahogy (ahogyan az előbb a határértékanalízissel kapott n értékek mellé is választottunk valahogy egy-egy k értéket), és a k értéke majd ehhez alkalmazkodik.
Döntési táblák¶
Ez a módszer akkor alkalmazható, amikor a probléma logikája igaz-hamis döntésekkel leírható, valamint az adott kombinációk esetén is binárisan tudjuk megmondani, hogy valamilyen "eredmény" keletkezik-e vagy sem. A módszer lényege, hogy feljegyezzük a döntéseket egy táblázatban, majd minden kombinációjukhoz meghatározzuk, hogy a lehetséges "eredmények" előállnak-e vagy sem? (Előfordulhatnak persze megadhatatlan kombinációk.)
Ha például az előző n alatt k programot vesszük, ott lehet azt nézni, hogy érvényes-e az input, azaz 0 ≤ n ≤ 62, illetve 0 ≤ k ≤ n. Ez ugye két döntés, amelyeknek minden kombinációját le kell tesztelni. A lehetséges (most éppen egymást kizáró) eredmények pedig a számolás és a "nem értelmezett" üzenet.
teszteset | 10. | 09. | 04. | 03. |
---|---|---|---|---|
n érvényes | n | n | i | i |
k érvényes | n | i | n | i |
számolás | n | n | n | i |
nem értelmezett | i | i | i | n |
Döntési tábla segítségével előálló, az n és k érvényes/érvénytelen kombinációját ellenőrző tesztek (példa):
10: n és k is érvénytelen: -5 alatt -3
Az input:
1 |
|
1 |
|
09: n érvénytelen, k érvényes: 63 alatt 2
Az input:
1 |
|
1 |
|
Ez fentebb már volt, de egy teszteset több technika alapján is megalkotható, ezzel nincs semmi probléma.
04: n érvényes, k érvénytelen: 3 alatt 5
Az input:
1 |
|
1 |
|
Ez fentebb már volt, de egy teszteset több technika alapján is megalkotható, ezzel nincs semmi probléma.
03: n és k is érvényes: 5 alatt 3
Az input:
1 |
|
1 |
|
Ez fentebb már volt, de egy teszteset több technika alapján is megalkotható, ezzel nincs semmi probléma.
De lehetséges az is, hogy az 0 ≤ n és n ≤ 62 feltételeket különszedjük (meg k-ra is 0 ≤ k és k ≤ n). Ekkor lesz pár lehetetlen kombináció, de összességében több tesztesetet eredményez.
- | 10. | 11. | 12. | - | - | 14. | 15. | 09. | - | 13. | 04. | 03. | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 ≤ n | n | n | n | n | n | i | i | i | i | i | i | i | i |
n ≤ 62 | n | i | i | i | i | n | n | n | n | i | i | i | i |
0 ≤ k | ? | n | n | i | i | n | n | i | i | n | n | i | i |
k ≤ n | ? | n | i | n | i | n | i | n | i | n | i | n | i |
számolás | - | n | n | n | - | - | n | n | n | - | n | n | i |
nem értelmezett | - | i | i | i | - | - | i | i | i | - | i | i | n |
Az így előálló teszteset-halmaz (például):
11: n < 0, n ≤ 62, k < 0, k ≤ n: -5 alatt -8
Az input:
1 |
|
1 |
|
10: n < 0, n ≤ 62, k < 0, k > n: -5 alatt -3
Az input:
1 |
|
1 |
|
::: n < 0, n ≤ 62, k ≥ 0, k ≤ n : -5 alatt ??
Ez a kombináció a k értékére vonatkozó feltételek miatt nem lehetséges.
12: n < 0, n ≤ 62, k ≥ 0, k > n: -5 alatt 8
Az input:
1 |
|
1 |
|
::: n < 0, n > 62, k < 0, k ≤ n: ?? alatt ??
Ez a kombináció az n értékére vonatkozó feltételek nem lehetséges.
::: n < 0, n > 62, k < 0, k > n: ?? alatt ??
Ez a kombináció az n értékére vonatkozó feltételek nem lehetséges.
::: n < 0, n > 62, k ≥ 0, k ≤ n: ?? alatt ??
Ez a kombináció az n értékére vonatkozó feltételek nem lehetséges.
::: n < 0, n > 62, k ≥ 0, k > n: ?? alatt ??
Ez a kombináció az n értékére vonatkozó feltételek nem lehetséges.
13: n ≥ 0, n ≤ 62, k < 0, k ≤ n: 5 alatt -8
Az input:
1 |
|
1 |
|
::: n ≥ 0, n ≤ 62, k < 0, k > n : 5 alatt ??
Ez a kombináció a k értékére vonatkozó feltételek nem lehetséges.
03: n ≥ 0, n ≤ 62, k ≥ 0, k ≤ n: 5 alatt 3
Az input:
1 |
|
1 |
|
04: n ≥ 0, n ≤ 62, k ≥ 0, k > n: 3 alatt 5
Az input:
1 |
|
1 |
|
14: n ≥ 0, n > 62, k < 0, k ≤ n: 65 alatt -8
Az input:
1 |
|
1 |
|
::: n ≥ 0, n > 62, k < 0, k > n : 65 alatt ??
Ez a kombináció a k értékére vonatkozó feltételek nem lehetséges.
09: n ≥ 0, n > 62, k ≥ 0, k ≤ n: 63 alatt 2
Az input:
1 |
|
1 |
|
15: n ≥ 0, n > 62, k ≥ 0, k > n: 65 alatt 70
Az input:
1 |
|
1 |
|
A fenti példákat a make test
paranccsal tudod futtatni.
Házi feladat
A tesztek alapján javítsd ki a nak
program hibáit!
Megjegyzendő, hogy bármilyen szisztematikus és alapos is a tesztelés, sosem biztosíthatja a program hibamentességét, csak csökkentheti annak valószínűségét, hogy a programban hiba marad.
Még több teszt?
Miután a fenti tesztek alapján kijavítottad a nak
programot, találsz-e olyan tesztesetet, ami újabb javítást tesz szükségessé?
Feladat¶
Adott a letölthető csomagban található kodolas.c
-ből fordított kodolas
program, aminek a feladata egy szöveg kódolása vagy dekódolása megadott kulcs alapján.
A kódoló/dekódoló program követelményei
A programmal szemben támasztott követelmények:
- A program egy kulcs alapján képes szövegek kódolására vagy dekódolására.
- A program az angol ábécé kis- és nagybetűit használja.
- A "normál" (dekódolt) szöveg kisbetűkből, a kódolt szöveg nagybetűkből áll.
- Egy betű kódolása egy kódoló kulcs alapján úgy történik, hogy a betű (0 bázisú) sorszámához (azaz 'a' és 'A' = 0, 'b' és 'B' = 1, ..., 'z' és 'Z' = 25) hozzáadjuk a kulcsot, és az eredmény a kapott sorszámú betű lesz, modulo 26 (vagyis körbemegyünk, a 'z' után megint az 'a' következik).
- Egy betű dekódolása egy kódoló kulcs alapján úgy történik, hogy a betű (0 bázisú) sorszámából kivonjuk a kulcsot, és az eredmény a kapott sorszámú betű lesz, modulo 26 (vagyis körbemegyünk, az 'a' előtt megint a 'z' következik).
- Az első betű kulcsát a felhasználó adja meg, minden ezt követő betű kódoló kulcsa az előző betű (0 bázisú) sorazáma.
- A felhasználó által adott kódoló vagy dekódoló kulcsot az input első teljes sora tartalmazza. Ha az első sorban lévő érték pozitív, akkor ez a kódoló kulcs, ha negatív, akkor dekódoló kulcs. (A dekódoló kulcs azt adja meg, hogy dekódoláskor mennyit kell hozzáadni a kódolt betűhöz, hogy visszakapjuk az eredetit. A kódoló és dekódoló kulcsok egymás -1-szeresei.)
- Azt, hogy kódolni vagy dekódolni kell, az input szó első betűje dönti el.
- Az input szóban csak az angol ábécé betűi szerepelhetnek.
- Ha az inputon nem megfelelő kulcs vagy karakter jön, a program további betűk kiírása és feldolgozása nélkül véget ér.
- Az output formátuma megegyezik az input formátumával, de mindenképpen kódoló kulcsot tartalmaz.
Vagyis a program a következőképpen kellene, hogy működjön.
Az input első sora egy egész szám, ami megmondja, hogy az első betűt mennyivel kell "eltolni" a kódoláshoz (pozitív) illetve dekódoláshoz (negatív). A 3-as eltolás például azt jelenti, hogy kódolásnál az 'a'-ból 'D', a 'b'-ből 'E', ..., az 'x'-ből 'A', ..., a 'z'-ből 'C' lesz. Dekódolásnál pedig fordítva, 'A'-ból 'x', ..., 'Z'-ből pedig 'w'. Azután mindig az előző nem kódolt betű 0-ás bázisú sorszáma határozza meg a következő betű "eltolását". Azaz 'a' betű esetén a következőt 0-val, 'b' esetén 1-gyel, ..., 'z' esetén pedig 25-tel kell "eltolni". A második sorban egy az angol ábécé csak kis- vagy csak nagybetűiből álló szöveg van. A kisbetűs szavakat kódolni, a nagybetűseket dekódolni kell.
A kimenet első sora a kódszám (mindenképpen a kódoláshoz megadva) a második sorában pedig a csupa nagybetűből álló kódolt, vagy csupa kisbetűből álló dekódolt szöveg. A kódolás/dekódolás közül első karakter alapján kell választani (és nem attól függ, hogy az első sorban a kódolás vagy dekódolás "eltolása" van-e megadva). Ha más karakter is van az inputon az a kimenet végét jelenti. Ha az első szám nem -25 és 25 között van (vagy nem szám), a program nem ír ki semmit.
Feladat
Készíts teszteket a programhoz, majd ezek alapján javítsd ki a hibáit. Csak akkor javíthasz ki egy hibát, ha van olyan teszt, amelyik felfedezte azt!
Ha készítesz egy test-kodolas.N.in
és egy test-kodolas.N.exp
fájlt, ahol az .in
a bemenet, az .exp
pedig az elvárt eredmény
(N pedig egy sorszám), akkor a Makefile
segítségével a make test-kodolas.N
paranccsal tudod majd futtatni a tesztet (vagy make test
parancsal az összeset).
A forráskódot ne nézd meg előre! Először próbáld meg a specifikáció alapján önállóan megtalálni a teszteseteket, mindet, amit el tudsz képzelni. Addig NE olvass tovább!
Mondom (írom) NE! STOP!
Ha mégis kellene egy kis segítség, akkor néhány tipp:
- kódoló vagy dekódoló kulcs van-e megadva?
- szöveg vagy kódolt szöveg van megadva?
- ezek kombinációja jól működik-e?
- milyen karaktereket fogad el a program?
- mi alapján dönt kódolásról/dekódolásról?
- jól kezeli-e a kódolandó/dekódolandó betűk intervallumát?