Vezdén Eszter Dialízis gép software komponensét alkotó unitok modul tesztje követelmény és struktúra alapon Kutatói beszámoló Ipari konzulens: Trenyik Ádám, B. Braun Medical Kft.
Kutatói ösztöndíjamat a B.Braun Medical Magyarország Orvostechnológiai Kft. nél töltöttem. Ezen időszak alatt főként unit teszteléssel foglalkoztam. Beszámolómban ismertetem a dialízisgépet szoftver szempontból, illetve a unit tesztelés mikéntjét, elveit és alkalmazását a gyakorlatban. Unit teszt Fejlesztéseink során számtalanszor szükség van módosításra, új igények megvalósítására. Ehhez a már meglévő kódhoz kell hozzányúlnunk, a meglévő funkciókat ki kell egészítenünk vagy újakat kell létrehoznunk. Osztályokat tervezünk újra, kódrészleteket emelünk ki, vagy esetleg csak újakat építünk be. Képzeljük el, hogy ezt nem csak egymagunk végezzük, hanem egy csapatban dolgozunk és mások is dolgoznak azon az osztályon, amelyen mi már változtattunk az igényeknek megfelelően. Az eredmény egy dinamikusan változó, jó esetben egy egyre jobban működő, hatékonyabb és funkciókban gazdagabb kód lesz, ami tükrözi az elvárt követelményeket. A folyamatos változtatás és fejlesztés során ellenőriznünk és ügyelnünk kell, hogy a már létező és jó működésben ne okozzunk zavart. Ezt a jól tervezett, szervezett és ellenőrzött kóddal tudjuk elérni. Tételezzük fel, hogy van egy logikai egységünk, amit a változtatás után is szeretnénk, hogy jól működjön, mondjuk egy osztályunk. Elvégzem a módosításokat, majd a hagyományos módon ellenőrzöm, hogy vajon jól működik e, majd a változtatást elmentem. Tételezzük fel, hogy valaki megint változtat rajta és megint ellenőrzi, hogy jól működik e. Az ellenőrzések, vagyis az osztályok, mint logikai egységek tesztelésére használhatunk előre megírt, automatizált teszteket is, amelyeket egyszer kell megírni, majd utána csak futtatni kell és esetleg karbantartani, ha egy változtatás érinti a már meglévő tesztet. Ezáltal egyrészt időt nyerhetünk, másrészt az automatizálás révén biztosak lehetünk benne belátható időn belül, ha jól írták, meg, akkor hibátlan lesz a végeredmény. A lényeg, hogy még fejlesztési időben kiderüljön minden rendellenes működés.
Teszteléskor eltérő tesztszinteket különböztetünk meg, attól függően, hogy mekkora részegységekre írjuk a tesztet. A legalacsonyabb szint a Unit teszt, ezután jön a modul, majd alrendszer és rendszer teszt. Tesztelési elvek A unit teszt alapjait képező tesztelési elvek a következők: Dijkstra: a tesztelés nem a hiba hiányát mutatja meg, hanem a meglétét Kaner/Bach: A működés azt jelenti, hogy a requirementek egy részét vmilyen mértékben lefedi A hibátlan kód téveszméje: pl. nincs elég teszteset, nem elég szigorúak Féregirtó paradoxon: tesztesetek elöregednek karbantartás Kimerítő tesztelés nem lehetséges A hibák csoportosulnak: egy hiba további hibákat eredményezhet az interakciók miatt. A hibák 80% a a kód 20% ában van Pareto Principle Minden teszt visszavezethető kell legyen egy requirementre Korai tesztelés: a tesztelést a lehető legkorábbi időpontban el kell kezdeni és előre meghatározott célokra kell összpontosítani Három féle hibatípust különböztetünk meg: Error: amikor bekerül a kódba Defect: még tesztelés során Failure: élő rendszerben Elméletben lehetséges olyan szoftvert írni, amely elsőre is tökéletesen működik. Ámbár a fejlesztést, így a hibák kialakulását elég sok tényező befolyásolja. A hibák kialakulásának oka eredendően elég sokféle lehet, például: Programozói hiba
Kommunikáció hiánya illetve félreértés Szoftver komplexitásából eredő hiba Requirementek változása Nem pontosan definiált requirementek Nem teljes a kommunikációt leíró adat definíció Szoros határidők, nem megfelelő tervezés Rosszul dokumentált kód: maintenance munkák és változások Development tool ok hibái Különböző scriptek Teszt, input, output Unit tesztelésnél egy egy egységet önmagában, elszeparálva vizsgálunk. Mégis biztosítanunk kell egy olyan szimulált környezetet, amely a tesztelt taszk szempontjából megegyezik az eredeti környezetével. Ennek létrehozására stubokat, jelen esetben dummy taszkokat használunk. Ezek a taszkok látszólag a tesztelt taszkhoz (továbbiakban TUT, task under test) kapcsolódó szomszédos unitok funkcióját látják el, valójában viszont, csak információs csatornát jelentenek a TUT és a tesztelést vezérlő Test Organizer ( továbbiakban TO ) között. Tehát a dummy taszkok mindössze üzenetet továbbítanak. Az üzenet váltás jelen esetben SRR technikával zajlik. Az SRR mozaikszó a Send, Receive, Reply szavakból tevődik össze. Az egyik taszk üzenetet küld ( Send ) a másik taszknak, aki Receive állapotban várakozik. Ekkor a küldő blokkolt állapotba kerül. Majd az üzenet megérkeztével és feldolgozásával, a taszk a küldőnek egy válasz ( Reply ) üzenetet küld, amely azt kibillenti blokkolt állapotából. Teszt hiba esetén felmerülhet, hogy az egyik taszk bennragad egy állapotban ( deadlock ). Ennek elkerülésére definiált egy time out érték, melynek leteltével a taszk automatikusan kibillentődik az állapotból. Maga a TO több feladatot lát el. Ezek közül az egyik és legfontosabb, hogy beállítja a CM ( common memory ) értékeket a kapott adatok alapján, ezután kiküldi azokat a tesztelt taszknak, amely végrehajta rajtuk az általa képviselt feladatot, majd Reply üzenet formájában
visszaküld a választ. A TO a kapott értékeket összehasonlítja az elvárt (Expected) értékekkel és jelzi a hibát avagy egyezést. a TO további feladata még a tesztek futtatása. Az egyes unitokhoz Processz ID k vannak rendelve, így minden egyes unit egyedileg azonosíthatóvá válik, külön processzekként futtatható és ezek alapján tudnak kommunikálni egymással, valamint ezen nevek alapján kapják tulajdonságaikat az egyes dummy taszkok. A tesztek futtatásához a TO nek az azonosításhoz megfelelő adatokra van szüksége. Ilyenek a már említett Processz ID k, a tesztelendő taszk neve, illetve az ahhoz kapcsolódó taszkok neve. Az utóbbiaknál fontos kikötés az is, hogy dummy taszkként jöjjenek létre. Kell még továbbá az include fájlok elérési útja, valamint az az elérési út ahova, az outputot helyezni szeretnénk, illetve maguknak a megírt teszteknek az elérési útja. Ezeket az adatokat configurációs fájlok tartalmazzák, melyekből létrhezoható egy lista. A teszt tényleges futtatását egy perl nyelven megírt script végzi, amely ezen lista alapján betölti a configurációs fájlokat, feldolgozza azok tartalmát, ezek alapján lérehozza a kimeneti könvytárakat, valamint a tesztben résztvevő taszkokat ( TO, dummyk, tesztelt taszk ), amelyekhez hozzárendeli a már említett Processz ID kat, inícializálja a különböző üzeneteket. A teszt lefutásának végeztével a TO kitöröl egy lezáró ( lock ) fájlt jelezvén a tesztelés végét. Ezáltal futási időben is megszakíthatóvá válik a tesztelés. A fájl megszűnésével, az adatok feldolgozásra kerülnek a perl script által. Az eredményből, sok más mellett HTML illetve log fájlok generálódnak, melyekből a teszt futása, vagy esetleges sikertelensége visszakövethető. Ellenőrizhető, hogy a már említett CM ek értéke megfelel e az elvárt értékeknek, valamint az egyes üzenetváltások, esetlegesen a nemvárt üzenetek és tulajdonságaik. LCOV használatával jól lekövethető, hogy teszt közben mely sorokra és feltételekre sikerült ráfutnunk, illetve hányszor, valamint százalékos kódlefedettségi adatokat is kapunk, megkönnyítve ezzel tesztelést. Minél nagyobb a lefedettség, illetve minél jobban igazodunk az elvárt értékekhez, annál jobban növeljük a fejlesztés során kialakuló hibák észrevételének lehetőségét.
Irodalomjegyzék http://dobrenteiistvan.hu/lang/hu/2011/10/23/a unit tesztek jelentosege a fejlesztes s oran.html Magyar Tamás, BSc szakdolgozat, 2015., Kandó Kálmán Villamosmérnöki Kar Óbudai Egyetem