Kihagyás

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
5 0
Az elvárt output:
1
5 alatt 0 = 1

02: n alatt n eset: 5 alatt 5

Az input:

1
5 5
Az elvárt output:
1
5 alatt 5 = 1

03: nem 0 alatt nem 0 eset: 5 alatt 3

Az input:

1
5 3
Az elvárt output:
1
5 alatt 3 = 10

04: n alatt n+x eset: 3 alatt 5

Az input:

1
3 5
Az elvárt output:
1
3 alatt 5 nem értelmezett!

05: invalid input eset: ''three'' alatt ''two''

Az input:

1
three two
Az elvárt output:
1
Hibás adat!

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 5
Az elvárt output:
1
-1 alatt 5 nem értelmezett!

07: alsó végpont: 0 alatt 0

A k értéke itt érvényes kell, hogy legyen.

Az input:

1
0 0
Az elvárt output:
1
0 alatt 0 = 1
Ha kombináljuk a technikákat, ez kiválthatja a 01-es tesztesetet.

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
62 31
Az elvárt output:
1
62 alatt 31 = 465428353255261088

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
63 2
Az elvárt output:
1
63 alatt 2 nem értelmezett!

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
-5 -3
Az elvárt output:
1
-5 alatt -3 nem értelmezett!

09: n érvénytelen, k érvényes: 63 alatt 2

Az input:

1
63 2
Az elvárt output:
1
63 alatt 2 nem értelmezett!

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
3 5
Az elvárt output:
1
3 alatt 5 nem értelmezett!

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
5 3
Az elvárt output:
1
5 alatt 3 = 10

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
-5 -8
Az elvárt output:
1
-5 alatt -8 nem értelmezett!

10: n < 0, n ≤ 62, k < 0, k > n: -5 alatt -3

Az input:

1
-5 -3
Az elvárt output:
1
-5 alatt -3 nem értelmezett!

::: 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
-5 8
Az elvárt output:
1
-5 alatt 8 nem értelmezett!

::: 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
5 -8
Az elvárt output:
1
5 alatt -8 nem értelmezett!

::: 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
5 3
Az elvárt output:
1
5 alatt 3 = 10

04: n ≥ 0, n ≤ 62, k ≥ 0, k > n: 3 alatt 5

Az input:

1
3 5
Az elvárt output:
1
3 alatt 5 nem értelmezett!

14: n ≥ 0, n > 62, k < 0, k ≤ n: 65 alatt -8

Az input:

1
65 -8
Az elvárt output:
1
65 alatt -8 nem értelmezett!

::: 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
63 2
Az elvárt output:
1
63 alatt 2 nem értelmezett!

15: n ≥ 0, n > 62, k ≥ 0, k > n: 65 alatt 70

Az input:

1
65 70
Az elvárt output:
1
65 alatt 70 nem értelmezett!

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?

Utolsó frissítés: 2023-02-01 11:01:06