Menü Bezárás

Tesztelés élesben (testing in production) – avagy hogyan tegyük a tesztelési folyamatunkat sokkal hatékonyabbá anélkül, hogy felesleges kockázatot vállalnánk

Ha azt halljuk, hogy valaki élesben teszteli az alkalmazását, az első reakció általában nem az szokott lenni, hogy az illető professzionális szoftvertesztelést végez. Pedig a tesztelés élesben (testing in production vagy QA in production) egy professzionális QA-megközelítés, aminek az alkalmazása bizonyos projektek esetén elkerülhetetlen, de ettől függetlenül is a legtöbb projekt szempontjából számos megfontolandó és alkalmazható ötletet és praktikát tartalmaz.

Jelen cikkben egy valódi nemzetközi projektben szerzett tapasztalataimat osztom meg: milyen kihívásokkal szembesültünk a hagyományos QA-folyamat alkalmazása közben, miért lett rá a válasz az élesben tesztelés, mit is jelent ez valójában, hogyan valósítottuk meg, milyen technikai és „emberi” akadályokkal szembesültünk, és milyen eredményeink származtak az élesben tesztelésből.

Pár szót a projektről és a szervezetről

A projekt egy sikeres B2B-termék Svájcban, ami több mint négy éve került bevezetésre a svájci piacra. A termék hasonló funkcionalitással rendelkezik, mint a jól ismert Dropbox vagy Google Drive, de egyedi megoldásokat is nyújt. A termék piacra dobása előtt és a fejlesztés közben is a svájci helyi igények és jellegzetességek figyelembevételével történt a termék irányítása.

A terméket jelenleg több mint 120.000 aktív felhasználó használja, egy részük ingyenesen, másik részük előfizetéses szolgáltatásként. A felhasználók személyes fájljainak tárolásáról lévén szó, a teljes rendszer hatalmas mennyiségű adathalmazt tárol (sok-sok petabájt), ami a mai felhasználói elvárásoknak megfelelően 24/7-es rendelkezésre állással működik.

A termék fejlesztése egy svájci nagyvállalatnál zajlik; egy 50 fős, motivált tagokból álló szervezet felel a termék fejlesztéséért és marketingjéért. A szervezet lényegében egy startupszervezetként működik a nagyvállalaton belül, és nagy autonómiával rendelkezik. Az üzleti célokat és azok teljesülését rendszeres időközönként tekintik át a felső vezetéssel.

A termék több altermékből is áll, ezek egyetlen ökoszisztémában egyesülnek. Külön alterméknek minősül az Android- és iPhone-kliens, a webes felület, a desktopkliens és a back office rendszer is.

Az élesben tesztelést a desktopkliensben valósítottuk meg.

A technológiai stack

Az említett desktopklienssel kapcsolatosan elvárás volt, hogy Windowson és Mac OSX-en is fusson, ezért a fejlesztés elején az Electront választott a fejlesztői csapat a UI fejlesztéséhez (ez magával hozta a HTML-t, CSS-t, Angulart és Typescriptet). A komplex fájlszinkronizációs logika implementálásához a csapat a Javát választotta (Spring Boot, Maven3). A fejlesztők nagyobbik része egyébként mélyreható javás ismeretekkel rendelkezett, ezért is esett a választás a Javára. Ezt a két alrendszert (Electronban írt UI és javás szinkronizáló logika) egy telepíthető alkalmazásban kellett egységesíteni.

A háttérrendszerek – amiket nagyobb részben más csapatok fejlesztettek – CloudFoundry platformot használtak (platform as a service megoldás), ami lehetővé teszi a háttérszolgáltatások egyszerű és rugalmas deploy-álhatóságát, skálázhatóságát és monitorozhatóságát (ElasticSearch, Kibana). Az adatbázist a MongoDB biztosította, amit az ökoszisztémában futó összes alkalmazás a saját adatainak tárolására használt, beleértve ebbe még a fájltároló szolgáltatásnak a fájlok metaadatának tárolását is. A fájlok tartalmának tárolását egy dedikált, 3rd party, vásárolt technológia végezte.

Git verziókövetőt és Jenkinst használt a csapat buildszerverként.

A kezdeti QA-folyamat

Kezdetben egy teljesen standard QA-folyamattal indult a csapat.

⦁ GitFlow-t használt a fejlesztői csapat a fejlesztés és a release-folyamat során.
⦁ A fejlesztők code review-zták egymás commitjait, ami pull requestek segítségével valósult meg.
⦁ Minden olyan commit, amely a develop vagy master branch-re került, automatikusan elindította az automata (unit-/integrációs) teszteket. Az automata tesztek hermetikus tesztek voltak, azaz nem igazi rendszereket, hanem azok szimulációit használták azért, hogy a tesztek ne függjenek a hálózattól vagy ezen alrendszerek elérhetőségeitől, így biztosítva a tesztek stabilitását.
⦁ A szoftver teszteléséért felelős csapattagok tesztkörnyezetben tesztelték az alkalmazás egyes verzióit. Ők lényegében manuális felfedező tesztelést folytattak.
⦁ Egy külsős cégtől crowdtestingszolgáltatást vettünk igénybe, hogy bővítsük a saját tesztelési kapacitásunkat. Őket egyrészt felfedező tesztelésre kértük fel, másrészt pedig néhány manuális teszt különböző környezetekben történő futtatására.
⦁ A csapat SCRUM-keretrendszeren belül, kéthetes sprintekben dolgozott. Célként a sprintek végén történő release-adást próbáltuk kitűzni.

Milyen kihívásokkal szembesültünk a hagyományos QA-folyamat során?

Különféle kliens- és hálózati konfigurációk. Az alkalmazásnak, ami egy desktopkliens-alkalmazás volt, és egy igen összetett automata fájlszinkronizációs megoldást valósított meg, több különböző operációs rendszeren, azok különféle változatain, különféle klienskonfigurációkon kellett futnia. Nem tudhattuk, milyen szoftverek vannak telepítve specifikusan a klienseken, és azok hogyan befolyásolják a mi alkalmazásunk működését (pl. antivírusszoftverek). A hálózati elérések is különböztek, a háttérrendszerek átmenetileg lehet, hogy nem voltak elérhetőek. Az alkalmazásnak ezeket mind kezelnie kellett beavatkozás nélkül. Ami ennél viszont sokkal érdekesebb kérdés volt, hogy hogyan teszteljük az alkalmazást úgy, hogy agilisak maradjunk, ergo ne lassuljunk be a „végzetesen” alapos tesztelés miatt, és képesek maradjunk a gyakori szállításra. Arra jutottunk, hogy ha éles környezetben mérnénk a meghibásodásokat, akkor a nagyszámú populáció párhuzamos „tesztelése” nagy szolgálatot tehetne nekünk, feltéve, hogy képesek vagyunk ezeket az inputokat hatékonyan feldolgozni.

Hibák fontosságának megállapítása. Találtunk hibákat a szoftverben, de egyrészt kezdetben nagyon sokat, másrészt sok időt vett el egy-egy javítás elkészítése és azok visszaellenőrzése a futási környezetekben használt heterogén technológiák miatt. Nagyon gyakran egy talált hiba során az analízis is sok időbe telt, akár napokba is (elosztott rendszerben sokszor nehéz visszakövetni, mi történt). Ahhoz, hogy hatékonyan tudjunk foglalkozni a hibákkal, jó lett volna tudni azt, hogy egy-egy hiba mennyire releváns, mennyi felhasználót érint. Ezt „élesbeli” adatok hiányában lehetetlen volt megállapítani, de még megbecsülni is.

A crowdtesting jelentős késleltetést okoz. Kéthetes sprintekben dolgozott a csapat, és szerettünk volna a sprintek végén release-elhető szoftvert előállítani (ahogy a SCRUM is előírja). A valóságban azonban ez úgy alakult, hogy a crowdtesting 4-5 napot is igénybe vett a sprint vége után, ami átlapolódott a követkető sprint első felével. Ugyanis a külső tesztelőket mindig fel kellett készíteni az új verzióra; milyen változások történtek, milyen részekre fókuszáljanak. Ezenfelül az általuk adott inputok feldolgozása is fáradságos és időigényes volt. Az írásbeli kommunikáció miatt sok esetben „félrementek” a dolgok, vagy egyszerűen nem tudtuk reprodukálni azt, amit ők találtak. Ezentúl, ugyanúgy nem tudták megtalálni azokat a típusú hibákat, amelyeket mi magunk is képtelenek voltunk megtalálni, mert ahhoz a konfigurációk számában sokkal nagyobb variációra lett volna szükség. Képtelenség volt a kéthetes sprinteket tartani, és az eredmények is megkérdőjelezték számunkra a crowdtesting alkalmazhatóságát a projektünkben.

Milyen sokáig teszteljük még az alkalmazást? A tesztelés során sosem tudtuk azt, hogy meddig lenne még érdemes tesztelni a szoftvert. Vajon előjött már minden jelentős hiba, vagy még érdemes tovább tesztelni? Ennek a problémának a gyökere visszavezethető a korábban említett kihíváshoz, hogy a különféle kliens- és hálózati konfigurációk, háttérrendszer-elérhetőségek és időzítések nagyon sok variációt hordoznak magukban. Sosem éreztük úgy, hogy biztonságosan release-elhetnénk a szoftvert.

Azok a hibák, amelyeket nem is veszünk észre, és később nagy gondot okoznak. Elég gyakori eset az, hogy egy felhasználó több tízezer fájlt tárol a cloudban. Képzeljük el azt a szituációt, amikor egy fájl valami miatt nem kerül feltöltésre, a felhasználónak tönkremegy a gépe, és amikor leszinkronizálja a fájljait, az említett fájl nem kerül letöltésre, mert az fel sem lett töltve előtte. Ilyenkor lehetetlen már bármit is csinálni, a régi fájl visszavonhatatlanul elveszett. Ezeknek a típusú hibáknak az a jellegzetessége, hogy amikor a felhasználó észreveszi őket, már túl késő. Ezek nagy reputációvesztést eredményezhetnek a terméknek és a vállalatnak is. Az ilyen típusú hibák megtalálásához képtelenek voltunk előállni egy használható tesztelési stratégiával a hagyományos QA-megközelítésben.

A fenti kihívások egyértelműen az élesben tesztelés irányába terelték a csapatot, ahol a csapatnak kellett automatikusan gyűjteni, analizálni, mérni és priorizálni a rendszerben éles használat során előforduló meghibásodásokat.

Mi az élesben tesztelés?

A hagyományos QA-megközelítésben a tesztelést a release-adás előtt végzik. Ha a verzió élesbe került, az üzemeltetői csapat folyamatosan monitorozza a rendszert, hogy az elérhető-e, vélhetően működik-e. Ha a felhasználók hibával szembesülnek, akkor – jobb esetben – felveszik a kapcsolatot a céggel, és jelentik az észlelt problémá(ka)t. Akkor feltételezhető, hogy nincs hiba a rendszerben, ha nem érkezik arra vonatkozó felhasználói bejelentés.

Az élesben tesztelés során a QA-folyamatot kiterjesztjük az éles rendszerre is. A minőséggel kapcsolatos problémákat a rendszer használatának monitorozásával tárjuk fel (ami különbözik az üzemeltetői monitorozástól):

Forrás: https://martinfowler.com/articles/qa-in-production.html

A mi esetünkben annyira költséges és időrabló lett volna a hagyományos preprod-környezetben történő tesztelés, hogy az a gyakorlatban lehetetlenné tette volna a termék elvárt minőségének biztosítását és a termék fenntartható fejlesztését, így a csapat számára nem volt kétséges, hogy át kell állni az élesben tesztelésre. Ez azonban nem mindenki számára volt egyértelmű, és a szervezetben sok aggodalomra is okot adott, ezért annak szükségességéről meg kellett győzni a szervezetben a különféle stakeholdereket.

Előkészületek az élesben tesztelés bevezetése előtt

Az élesben tesztelés előfeltétele az, hogy ha hibát találunk az éles rendszerben, akkor rövid időn belül képesek legyünk azt javítani. Ez nem jelenti azt, hogy minden éles rendszerbeli hibát azonnal ki fogunk javítani, de a lehetőségnek fenn kell állnia arra, hogy egy javítást soron kívül release-elhessünk. A hagyományos megközelítések a „hibamentesség” jegyében alapos tesztelésnek vetik alá a rendszert, és ha mégis „félresikerült” a release, akkor akár vissza is állhatnak egy korábbi verzióra (roll back). Manapság sok esetben a roll forward stratégiát alkalmazzák, azaz, ha félremegy az új verzió, akkor kiadnak egy újabbat, ami javítja az előző hibáját. A mi esetünkben, amennyiben megtörtént a javítás, akkor az új release-t a buildfolyamatunk segítségével kb. 30 perc alatt ki lehetett adni.

Ahhoz, hogy képesek legyünk a gyors és gyakori release-adásra, fel kellett javítanunk az akkori release-folyamatunkat.

Egyhetes release-ciklusok. A csapat eldöntötte, hogy hetenként fog release-elni. Minden kedd release-nap lett (ettől függetlenül a SCRUM-iteráció kéthetes maradt.) Ez azért volt fontos, mert kezdetben sok hibajavítást kellett végeznünk, és a kéthetes ciklus egyszerűen túl hosszú lett volna ehhez. A későbbiekben is hasznosnak bizonyultak a heti release-ek, hiszen ha bekerült valamilyen hiba, akkor hamar tudtuk javítani a normál folyamattal. Ráadásul voltak olyan hibák, amelyek kijavítása heteket vagy hónapokat vett igénybe. Ezt csak iteratívan tudtuk elvégezni, folyamatos javítgatással. Ha hetente release-elünk, kétszer olyan gyorsan tudunk egy nagyobb lélegzetvételű hibát javítani, mint ha kéthetes release-eink lennének.

Automatikus frissítések. Egy desktopkliens-alkalmazást a felhasználó maga telepít, és sok alkalmazás esetében új verziónál is maga a felhasználó tölti le a frissítést. Ez a mi esetünkben nem volt járható út. A gyakori release-adás csak akkor működhet, ha a szoftver önmagát képes frissíteni felhasználói beavatkozás nélkül.

Trunk-based development. Gitflow branching modell helyett átálltunk a trunkalapú fejlesztésre, azaz minden fejlesztő közvetlenül a master branchre commitált. A continuous integration csak akkor valósulhat meg, ha a kód mindennap integrálva van, ezt pedig így tudtuk kikényszeríteni a teljes fejlesztői csapaton belül. A fejlesztői csapatnak meg kellett tanulnia, hogyan tud egy nagyobb ívű (több napos, hetes vagy akár hónapos) fejlesztést is apró commitok sorozataként szállítani, így feature toogle-ket is elkezdtünk használni.

Tesztelés éles backendrendszerekkel. Korábban a desktopklienst tesztkörnyezetben teszteltük, azaz az új, kiadás előtti verziót tesztkörnyezetben futó backendrendszerekkel teszteltük. Ennek megvolt az a hátulütője, hogy ha valamilyen hibát detektáltunk, soha nem lehettünk abban biztosak, hogy az a desktopkliens vagy a fejlesztés és tesztelés alatt álló backendrendszer hibája volt-e. A legegyszerűbb az volt, ha kimondjuk, hogy mindig éles rendszerben futó backendrendszereket használunk, mert azok a legstabilabbak.

Crowdtesting mellőzése. Crowdtestinget a normál deployment pipeline-unkból eltávolítottuk, és csak kivételes esetekben amikor láttuk a hozzáadott értéket alkalmaztuk. Ez a gyakorlatban nagyon ritkán fordult elő.

Az élesben tesztelés kulcsa: canary releasing

Az élesben tesztelés kulcsa az ún. canary releasing. Ez azt jelenti, hogy a rendszert először a felhasználók töredékének tesszük csak elérhetővé, ezáltal korlátozva az új verzió esetleges negatív hatását. Ezután meggyőződünk arról, hogy ebben a szűk felhasználói körben a minőségi feltételeknek megfelelően működik a szoftver. Ez tipikusan adatvezérelten történik; előre implementált metrikákat használunk arra, hogy egyedi döntést hozzunk. Ha az a döntés születik, hogy az új szoftververzió a minőségi feltételeknek megfelel, kiengedjük azt egy még szélesebb körnek. Ez lehet a teljes felhasználói bázis vagy egy újabb limitált kör. Ezt addig folytatjuk, amíg az összes felhasználónak elérhetővé nem tesszük a szoftver új verzióját.

Release-adás lépésekben

A continuous delivery elvei alapján minden egyes változtatás, amit a fejlesztők végeznek (ekkor már csak master branchen dolgoztak), release candidate-nek (RC) tekintendő. A tesztelési folyamat egyes lépései igyekeznek meggátolni, hogy egy RC élesbe kerüljön, azaz az a cél, hogy minél korábban kiderüljön, ha alkalmatlan release-nek. Ha pl. nem futnak le az automata tesztek, akkor az RC megbukott, és nem léphet a következő lépcsőfokra a deployment pipeline-ban.

Minden egyes commit után, amennyiben a commit utáni változás után az automata tesztek lefutottak, az előállt build automatikusan telepítésre került egy belső felhasználói kör számítógépeire. Ez naponta akár többszöri telepítést is jelentett. Így már nagyon hamar adatokat tudtunk gyűjteni az új szoftververzióról, annak potenciális problémáiról.

Keddenként release-nap volt. Ha mindent rendben találtunk (elmúlt egy hét commitjainak utolsó ellenőrzése, belső körös felhasználók visszajelzéseinek figyelembevétele), akkor az új verziót elérhetővé tettük a felhasználók kb. 1%-ának. A metrikákat folyamatosan figyeltük, hogy a változás okoz-e valamilyen eltérést a számokban. Amennyiben rendben találtunk mindent, akkor egy pár óra után, még aznap kiengedtük a release-t az összes felhasználónak.

Implementált metrikák

Ahhoz, hogy megalapozottan el lehessen dönteni, hogy egy adott változásnak mi a hatása a felhasználókra nézve, mérési adatokat (metrikákat) szükséges gyűjteni a rendszer használatával kapcsolatosan.

Meghibásodások felismerése

A desktopkliens kódjában a kivételkezelést továbbfejlesztettük oly módon, hogy minden olyan kivételről, amely programhibára utalt, automatikusan hibabejelentést küldtünk a backendnek. A hibabejelentés részeként elküldtük a környezet paramétereit (pl. OS-verzió, futó processzek, fizikai memória mérete, elérhető memória stb.), a szoftver verzióját, a stacktrace-t és az alkalmazás logját. Ezeket a bejelentéseket utána egy saját fejlesztésű eszközzel automatikusan elemeztük.

Ez a riport a hibaelemző outputja (az üres részek érzékeny információkat tartalmaznak, ezért maszkolva lettek). Látható, hogy ez a riport a 17.30.3-as verzióról ad információt, ami az alkalmazás egy korai verziója volt. A begyűjtött meghibásodások a felhasználók száma szerint csökkenő sorrendben találhatóak a listában:

⦁ ERROR_SYMLINK: Ez a leggyakoribb hiba, ami 141 felhasználót érintett a vizsgált idősávban. Ez a hiba arról tanúskodik, hogy a desktopkliens nem képes megfelelően kezelni, ha a helyi fájlrendszeren symlinkek találhatóak.

⦁ ERROR_CANNOT_WRITE_SETTINGS_FILE: Ez a második leggyakoribb hiba, ami arra utal, hogy az alkalmazás a saját settingsállományát valamilyen okból kifolyólag – bizonyos esetekben – nem képes felülírni. Ezt a hibát hónapokon keresztüli folyamatos javítgatással tudtuk csak megszüntetni, mert több nem triviális gyökérokra is visszavezethető volt. Pl. kiderült, hogy bizonyos esetekben antivírus szoftver zárolta az állományt.

⦁ ALERT_VERY_SLOW_STARTUP: Néhány felhasználó jelezte, hogy az alkalmazásnak az elinduláshoz több percre is szüksége van. Nem tudtuk, mi állhat a probléma hátterében, és azt sem tudtuk, hogy ez a hiba hány felhasználót érinthet, ezért az alkalmazásban implementáltunk egy külön logikát, ami az elindulási időt mérte, és ha ez egy bizonyos T időnél nagyobb volt, akkor meghibásodást jelentett. A beküldött információk alapján láttuk, hogy ez viszonylag sok felhasználót érintett, és képesek voltunk sok elemzés után megfejteni, mi áll a hiba hátterében. Kiderült, hogy az egyik backendrendszerünk volt lassú bizonyos helyzetekben, amit egyébként egy másik csapat fejlesztett.

⦁ ERROR_8125_OUT_OF_MEMORY: Ahogy a neve is mutatja, az alkalmazás felhasználta az összes rendelkezésre álló memóriát. Hosszú hónapokig tartott, amíg apró javításokkal képesek voltunk ezt a problémát orvosolni. A probléma hátterében változatos gyökérokok álltak.

A listában szereplő meghibásodások nagy részére igaz, hogy a csapatnak esélye se lett volna azokat a hagyományos teszteléssel korlátozott időn belül a rendelkezésre álló erőforrásokkal előidézni és javítani. Továbbá azt sem tudtuk eldönteni, hogy a hiba hány felhasználót érinthet, és hogy a javításunk milyen mértékben volt képes a hibát megszüntetni.

A meghibásodások nevében található azonosító a JIRA issue-követőnkben létrehozott issue sorszáma, így könnyen megfeleltethető a hibariportban található hiba a JIRA-ban található hibákkal. Az UNKNOWN nevezetű hiba (utolsó előtti elem a listában) olyan hibára utal, amely új hibaként került be a rendszerbe, és a meghibásodáselemző még nem tudta felismerni. Ha UNKNOWN hiba szerepelt a listában, akkor az elemzőt felkészítettük ennek a hibának a felismerésére is, így az a következő futtatáskor már ezt a specifikus hibát is külön szerepeltette a listában.

Konsziztenciaarány (consistency rate): a KPI-unk

Az alkalmazás core funkciója a fájlok szinkronizációja. A korábban már említett, nehezebben észrevehető fájlszinkronizációs hibák detektálása végett szükséges volt bevezetnünk egy mérőszámot, ami a fájlszinkronizáció helyességét méri rendszerszinten.

Minden telepített alkalmazáspéldány időről időre összehasonlítja a helyi fájlrendszer fájljainak metaadatát (útvonal, fájlméret, utolsó módosítás dátuma) a távoli cloudos tárolóban lévő fájlok metaadatával. Ideális esetben a metaadatoknak egyezniük kell („OK”). Ha különbség adódik, akkor az hibára utalhat, és azt minden esetben meg kell vizsgálni („FAILED”).

Ha a fájlszinkronizáció éppen fut, akkor a helyi és a távoli metaadatok különbözhetnek; ezt nem tekintjük hibának („BUSY”). Ha azonban a fájlszinkronizáció nem fejeződik be egy meghatározott időn belül, az arra utalhat, hogy a fájlszinkronizációs logika végtelen ciklusba került („STUCK”).

Egyéb metrikák

Az idők során számos egyéb metrikát is implementáltunk, amiket egy dashboardon transzparenssé tettünk az összes csapattag számára.

A dashboardon pl. követtük a már említett meghibásodások számának változását az idő függvényében („number of client errors”) – ez segített nekünk gyorsan detektálni, ha az új verzió telepítése után olyan hibák kerültek a rendszerbe, amelyek sok felhasználót érintettek.

A csapat a desktopkliens teljes telepítési folyamatát is elkezdte monitorozni. Figyeltük, hol akad el a felhasználó, és ennek mi lehet az oka; lehet, hogy programhiba, lehet, hogy félbeszakadt letöltés, lehet, hogy meggondolta magát a felhasználó – a végeredmény szempontjából igazából mindegy is: nem telepítette fel az alkalmazást, és ezen érdemes lehet javítani.

Mivel a célunk az volt, hogy a desktopkliensek automatikusan frissüljenek, ezért folyamatosan monitoroztuk a régi kliensverziókat. Ha valami miatt a régi verziók nem frissültek, annak okát is ki kellett vizsgálnunk.

Eredmények

A csapat immáron két éve fejleszti azokat az eszközöket, amelyek segítik a testing in production alkalmazásához az adatok begyűjtését és azok transzparenssé tételét. A begyűjtött adatok lehetővé teszik, hogy a jelentkező issue-khoz megfelelő prioritást rendeljünk, hiszen ismert, hogy hány felhasználót érint az adott issue. Ez alatt a két év alatt a csapat képessé vált:

⦁ a konzisztenciaarányt (KPI) 97%-osra növelni (a kezdeti 60%-ról),
⦁ egyhetes release-ciklusokat tartani úgy, hogy közben a kiadott release-ek stabilak maradtak,
⦁ az adatok lehetővé tették az issue-k transzparenssé tételét és egyértelmű priorizálását,
⦁ a csapat magabiztosságot szerzett és bizalmat vívott ki a szervezeten belül, mert képes volt kontroll alatt tartani a terméket.

Az emberi tényező

A testing in production bevezetése előtt a csapaton belül is meg kellett szerezni a megfelelő támogatást, utána pedig a menedzsmenttel is egyeztetni kellett a megközelítésről.

Azt mindenki belátta, hogy az adatok összegyűjtése a kliensekről szükséges, hiszen a desktopkliens-alkalmazás hibáiról másképpen nem értesülhetünk. Azt volt nehezebb megértetni a részt vevő felekkel, hogy ne a preprod-környezetben próbáljuk „hibamentessé” tenni a szoftvert, mert az nagyon lassú és igen költséges lenne. Azok, akik a projektben nem vettek részt, ezt nehezen értették meg, ezért inkább a hagyományos tesztelési megközelítést preferálták. A svájci nagyvállalati környezetben a biztonságosság és a reputáció fontos értékek, ezt a csapat is tudta, de a csapat azzal is tisztában volt, hogy ezt a crowdtestingszolgáltatással és pár manuális tesztelővel nem lehet biztosítani, sokkal nagyobb variancia és valódi adatok szükségesek a realitás érzékeléséhez, ezt pedig csak éles környezetben lehet biztosítani.

Az architect is nehezen ment bele a változtatásokba. Ő felelt azért, hogy az összes projekt hasonló standardok alapján működjön. A desktopkliens „letért erről az útról”, nem használt Gitflow-t, hanem közvetlenül a masterre commitolt, a kéthetes release-ek helyett heti release-ekben kerültek ki az új verziók, tesztkörnyezet helyett minden éles backendrendszereken keresztül lett tesztelve, és a crowdtesting lényegében elhagyásra került. Ezek a folyamatelemek voltak hivatottak a minőséget növelni a teljes termék egyes altermékeiben.

A csapat végül is kedvező helyzetben volt, mert a termék lényeges lemaradásban volt az ütemtervhez képest, és mivel a motivált csapat nagyon hitt abban, hogy ezzel a módszerrel felgyorsíthatja a piacra lépést, és a hibákat sokkal gyorsabban javíthatja, ezért végül a menedzsment is elfogadta a változtatásokat. Ehhez szükség volt a menedzsment részéről a bizalom megelőlegezésére is a csapat felé.

A hagyományos QA-megközelítéssel dolgozó kollégák nehezen tudtak alkalmazkodni az új megközelítéshez. A manuális teszteléssel töltött hosszú idő hatékonyságában egyre kevésbé tudott hinni a csapat. Mindenkinek, aki QA-val szeretett volna foglalkozni, alapvetően a testing in production megközelítést támogató eszközök megálmodásában és kialakításában kellett részt vennie.

A csapat nagyon motivált volt. Sikerekre vágytak, gyors eredményekre, és hittek magukban. Sokszor a PO megkérdezése nélkül a tervezett feladatok mellett építették a hibabegyűjtő és -elemző rendszert, és építették a dashboardot. Miután a PO is látta, hogy ezek mennyire hasznosak, könnyebben lehetett ezek továbbfejlesztésére is sztoripontot kérni, azonban általánosságban elmondható volt, hogy a PO nem szívesen áldozott ezen eszközök fejlesztésére. A PO úgy gondolkozott, hogy ha hiba van, akkor az a felhasználók bejelentései alapján úgyis felszínre kerül, a fejlesztői csapat viszont abban hitt, hogy a hibákat sokkal nagyobb ütemben, sokkal proaktívabban szükséges javítani, és kordában is kell azokat tartani, különben később sokkal nagyobb árat fognak érte fizetni. A PO és a csapat közötti véleménykülönbség okaként az valószínűsíthető, hogy a projekt komplexitását nem az üzleti domain komplexitása adta, hanem az a nagy technológiai komplexitás, amelyet elsősorban a fejlesztők éreztek a saját bőrükön. A csapat volt felelős a termék sikeréért, emellé nagy fokú autonómiával is rendelkezett.

Konklúzió

A testing in production a hagyományos gondolkozás szerint nem szerencsés, hiszen a hibát el lehetne kerülni preprod-környezetben történő teszteléssel ahelyett, hogy hagyjuk, hogy a hiba élesben bekövetkezzen. A gyakorlatban viszont sok esetben a hibát nem is veszi észre a felhasználó, vagy a hibát korlátozzuk egy kis felhasználói populációra (canary releasing). Mindkét esetben kijelenthető, hogy a teljes felhasználói bázist tekintve a megközelítés proaktív, tehát idejekorán értesülhetünk a minőségi problémákról, mielőtt azok még eszkalálódnának.

Nem minden projektnél lehet annyira hangsúlyos ez a tesztelési megközelítés, mint az említett projektben, de mindenképpen érdemes elgondolkozni azon, hogy hogyan lehetne értesülni az élesben bekövetkező hibákról még azelőtt, hogy a felhasználók jelentenék be azt.

Az említett termékfejlesztésben két év távlatából egyértelműen kijelenthető, hogy a termék sikere elképzelhetetlen lett volna a testing in production megközelítés alkalmazása nélkül.

A testing in production alkalmazásához mindenképpen szükséges egy motivált csapat, ami proaktívan akarja megtalálni a hibákat a szoftverben, és nem akar várni addig, amíg a felhasználók észreveszik és bejelentik azokat.

Olyan környezetben lehet alkalmazni ezt a megközelítést, ahol a hosszú távú szempontok figyelembevétele közös értéknek számít, és a csapat teljes felelősséggel (keresztfunkcionális + devops) és autonómiával rendelkezik. Ha a fejlesztői csapat nem érzi a fejlesztés során, hogy felelősséggel tartozik a termék sikeréért („majd más úgyis szól, ha hiba van benne”), vagy nem választhatják meg a saját módszereiket, akkor a testing in production nem valósulhat meg.

A csapattól fegyelmezettséget követel ez a működés a gyakori (ebben az esetben heti) release-adás miatt, és az élesben bekövetkező hibákra is képesnek kell lennie azonnal reagálnia. (Ez utóbbi leginkább release-adás után érdekes.) A rendszer folyamatos monitorozása egy újabb felelősségi köre a csapatnak, ami nem egyenlő az üzemeltetéshez kapcsolódó monitorozással, ami esetleg részben vagy egészben átadható egy üzemeltetői csapatnak.

A testing in production nem jelenti azt, hogy nem tesztelünk az éles környezet előtt; továbbra is nagyon fontos az éles előtti tesztelés. A megfelelő automata tesztek és a szükséges minimális manuális tesztelés ugyanúgy alapja annak, hogy egy új verziót éles környezetbe telepíthessünk.

A szerző

Marhefka István
Marhefka Istvánfüggetlen agile coach, software architect at T-shaped Software Kft.
Szeretném a szoftverfejlesztést sokkal emberibbé tenni; megmutatni, hogyan lehet figyelembe venni az emberek egyéni motivációit és tehetségét, és hogyan tudnak így együtt, egy csapatként hatékonyan szoftvert fejleszteni.
Vissza