Megosztás:


A tesztelés korábbi szakaszra helyezése egységtesztekkel

A tesztelés segít biztosítani, hogy a kód a várt módon teljesítsen, de a tesztek készítésének ideje és erőfeszítése időt vesz igénybe más feladatoktól, például a funkciófejlesztéstől. Ezzel a költséggel fontos, hogy maximális értéket nyerjen ki a tesztelésből. Ez a cikk a DevOps tesztelési alapelveit ismerteti, amelyek az egységtesztelés értékére és a bal oldali tesztstratégiára összpontosítanak.

A legtöbb teszt írásához dedikált tesztelők használtak, és sok termékfejlesztő nem tanult meg egységteszteket írni. A tesztek írása túl nehéznek vagy túl sok munkának tűnhet. Szkeptikus lehet, hogy működik-e az egységtesztelési stratégia, rossz tapasztalatok vannak-e rosszul megírt egységtesztekkel, vagy attól tart, hogy az egységtesztek lecserélik a funkcionális teszteket.

Az egységtesztelés bevezetésének argumentumait leíró ábra.

Egy DevOps-tesztstratégia implementálásához legyen pragmatikus, és összpontosítson a lendület kiépítésére. Bár ragaszkodhat az új kód vagy a meglévő kód egységtesztjeihez, amelyek tisztán újrabontásra kerülhetnek, érdemes lehet egy örökölt kódbázisnak engedélyeznie bizonyos függőségeket. Ha a termékkód jelentős része SQL-t használ, az egységtesztek függőséget vehetnek az SQL-erőforrás-szolgáltatótól, ahelyett hogy ezt a réteget mockolnák. Ez rövid távú megközelítés lehet a haladás érdekében.

Ahogy a DevOps-szervezetek kiforrnak, a vezetőség könnyebben fejleszti a folyamatokat. Bár lehet némi ellenállás a változásokra, az agilis szervezetek értékelik azokat a változásokat, amelyek egyértelműen megérik. Könnyen el kell adni a gyorsabb tesztfuttatások elképzelését kevesebb hibával, mivel több időt jelent az új érték létrehozásába való befektetés a funkciófejlesztéssel.

DevOps-teszt taxonómiája

A DevOps tesztelési folyamatának fontos eleme a tesztelési osztályozás meghatározása. A DevOps-teszt taxonómiája az egyes teszteket függőségeik és a futtatásuk ideje szerint sorolja be. A fejlesztőknek tisztában kell lenniük a különböző forgatókönyvekben használható tesztek megfelelő típusaival, valamint a folyamat különböző részeinek tesztelésével. A legtöbb szervezet négy szinten kategorizálja a teszteket:

  • Az L0 és L1 tesztek egységtesztek, vagy olyan tesztek, amelyek a tesztelés alatt álló szerelvény kódjától függnek, és semmi más. Az L0 a gyors, memórián belüli egységtesztek széles osztálya.
  • Az L2olyan funkcionális tesztek, amelyekhez szükség lehet az összeállításra és más függőségekre, például az SQL-re vagy a fájlrendszerre.
  • Az L3 funkcionális tesztek tesztelhető szolgáltatástelepítéseken futnak. Ez a tesztkategória szolgáltatástelepítést igényel, de előfordulhat, hogy a kulcsszolgáltatás-függőségekhez csonkokat használ.
  • Az L4-tesztek az élesben futtatott integrációs tesztek korlátozott kategóriájába tartoznak. Az L4-tesztekhez teljes terméktelepítés szükséges.

Bár ideális lenne minden teszt futtatásához, ez nem kivitelezhető. A Teams kiválaszthatja, hogy a DevOps-folyamat hol futtatja az egyes teszteket, és a shift-left vagy a shift-right stratégiák használatával áthelyezheti a különböző teszttípusokat a folyamat korábbi vagy újabb verzióiban.

Előfordulhat például, hogy a fejlesztők a véglegesítés előtt mindig L2-teszteket futtatnak, a lekéréses kérelmek automatikusan meghiúsulnak, ha az L3 teszt futtatása meghiúsul, és az üzembe helyezés le lesz tiltva, ha az L4-tesztek sikertelenek. Az egyes szabályok szervezetenként eltérőek lehetnek, de a szervezeten belüli összes csapatra vonatkozó elvárások érvényesítése mindenkit ugyanarra a minőségi jövőképre ösztönöz.

Egységtesztelési irányelvek

Szigorú irányelveket állíthat be az L0 és L1 egységtesztekhez. Ezeknek a teszteknek nagyon gyorsnak és megbízhatónak kell lenniük. Egy szerelvény L0-tesztjeinek átlagos végrehajtási ideje például 60 ezredmásodpercnél kisebb lehet. A szerelvény L1-tesztjeinek átlagos végrehajtási ideje kisebb, mint 400 ezredmásodperc. Ezen a szinten egyetlen teszt sem haladhatja meg a 2 másodpercet.

Egy Microsoft-csapat több mint 60 000 egységtesztet futtat párhuzamosan kevesebb mint hat perc alatt. Céljuk, hogy ezt az időt egy percnél rövidebbre csökkentsék. A csapat nyomon követi az egységtesztek végrehajtási idejét olyan eszközökkel, mint az alábbi diagram, és hibajegyeket nyit a megengedettnél hosszabb futási idejű tesztek ellen.

A tesztvégrehajtási időre összpontosító folyamatos fókuszt megjelenítő diagram.

Funkcionális tesztelési irányelvek

A funkcionális teszteknek függetlennek kell lenniük. Az L2-tesztek fő koncepciója az elkülönítés. A megfelelően izolált tesztek bármilyen sorrendben megbízhatóan futtathatók, mivel teljes mértékben szabályozhatják a környezeteket, amelyekben futnak. Az állapotnak a teszt elején ismertnek kell lennie. Ha egy teszt adatokat hozott létre, és az adatbázisban hagyta, az egy másik adatbázisállapotra támaszkodó teszt futtatását ronthatja.

A felhasználói identitást igénylő régebbi tesztek külső hitelesítésszolgáltatókat is meghívhattak az identitás lekéréséhez. Ez a gyakorlat számos kihívást jelent. Külső függőség megbízhatatlan lehet, vagy átmenetileg nem érhető el, ami a teszt megszakadásához vezethet. Ez a gyakorlat a tesztelkülönítés elvét is sérti, mivel egy teszt megváltoztathatja az identitás állapotát, például az engedélyeket, ami más tesztek esetében váratlan alapértelmezett állapotot eredményez. Fontolja meg ezeknek a problémáknak a megelőzését azáltal, hogy a tesztelési keretrendszeren belül az identitástámogatásba fektet be.

DevOps-teszt alapelvei

A tesztportfólió modern DevOps-folyamatokra való áttéréséhez fogalmazza meg a minőségi látásmódot. A Teamsnek be kell tartania a következő tesztelési alapelveket a DevOps-tesztelési stratégia meghatározásakor és megvalósításakor.

A minőségi látásra példaként szolgáló diagram, amely a tesztelési alapelveket sorolja fel.

Shift balra a korábbi teszteléshez

A tesztek futtatása hosszú időt vehet igénybe. A projektek méretezése során a tesztelési számok és a típusok jelentősen növekednek. Amikor a tesztcsomagok futása órákig vagy napokig tart, a végrehajtásuk gyakran az utolsó pillanatra tolódik. A tesztelés kódminőségi előnyei csak a kód véglegesítését követően valósulnak meg.

A hosszú ideig futó tesztek olyan hibákat is okozhatnak, amelyek kivizsgálása időigényes. A Teams képes toleranciát kialakítani a hibákra, különösen a futamok korai szakaszában. Ez a tolerancia aláássa a tesztelés értékét, mint a codebase minőségére vonatkozó megállapításokat. A hosszú ideig futó, utolsó perces tesztek kiszámíthatatlanságot adnak a futam végi elvárásokhoz, mivel ismeretlen mennyiségű technikai adósságot kell fizetni a kód szállíthatóvá ásához.

A tesztelés balra tolásának célja a minőség feljebb helyezése a folyamat korábbi szakaszában végzett tesztelési feladatok végrehajtásával. A tesztelési és folyamatfejlesztések kombinációjával a bal oldali váltás csökkenti a tesztek futtatásához szükséges időt, valamint a ciklus későbbi szakaszaiban fellépő hibák hatását. A balra tolás biztosítja, hogy a legtöbb tesztelés befejeződjön, mielőtt egy módosítás összeolvadna a fő ágtal.

Diagram a shift-left tesztelés felé való elmozdulásról.

Amellett, hogy a kódminőség javítása érdekében bizonyos tesztelési feladatokat áthelyeznek, a csapatok a DevOps-ciklusban jobbra vagy később más tesztelési szempontokat is áthelyezhetnek a végtermék javítása érdekében. További információért lásd: Shift right, azaz a szolgáltatás éles környezetben való tesztelése.

Tesztek írása a lehető legalacsonyabb szinten

További egységtesztek írása. A legkevesebb külső függőséggel rendelkező teszteket részesíti előnyben, és a legtöbb teszt futtatására összpontosít a build részeként. Vegyünk egy párhuzamos buildrendszert, amely képes egységteszteket futtatni egy összeállításhoz, amint az összeállítás és a kapcsolódó tesztek elkészültek. Ezen a szinten nem lehetséges a szolgáltatás minden aspektusának tesztelése, de az alapelv az, hogy könnyebb egységteszteket használjon, ha ugyanazokat az eredményeket tudják előállítani, mint a nehezebb funkcionális tesztek.

Cél a megbízhatóság tesztelése

A megbízhatatlan teszt fenntartása szervezetileg költséges. Egy ilyen teszt közvetlenül szembemegy a mérnöki hatékonysági céllal, mivel megnehezíti a magabiztos változtatásokat. A fejlesztőknek bárhol végre kell hajtaniuk a módosításokat, és gyorsan meg kell győződni arról, hogy semmi sem tört el. Tartson fenn magas szintet a megbízhatóság érdekében. A felhasználói felületi tesztek használatának elriasztása, mivel ezek általában megbízhatatlanok.

Bárhol futtatható funkcionális tesztek írása

A tesztek speciális integrációs pontokat használhatnak, amelyeket kifejezetten a tesztelés engedélyezésére terveztek. Ennek a gyakorlatnak az egyik oka, hogy maga a termék nem tesztelhető. Sajnos az ilyen tesztek gyakran belső tudástól függenek, és olyan implementációs részleteket használnak, amelyek funkcionális teszt szempontjából nem számítanak. Ezek a tesztek olyan környezetekre korlátozódnak, amelyek rendelkeznek a tesztek futtatásához szükséges titkos adatokkal és konfigurációval, ami általában kizárja az üzemeltetési környezeteket. A funkcionális teszteknek csak a termék nyilvános API-ját kell használniuk.

Termékek tervezése a tesztelhetőség érdekében

Az érlelt DevOps-folyamatokban lévő szervezetek teljes áttekintést nyújtanak arról, hogy mit jelent egy minőségi termék felhőbeli ütemben történő kézbesítése. Az egyensúly erőteljes eltolása az egységtesztelés és a funkcionális tesztelés mellett megköveteli, hogy a csapatok olyan tervezési és megvalósítási döntéseket hozzanak, amelyek támogatják a tesztelhetőséget. Különböző elképzelések vannak arról, hogy mi számít jól megtervezett és jól implementált kódnak a tesztelhetőség érdekében, ahogyan különböző kódolási stílusok is léteznek. Az alapelv az, hogy a tesztelhetőség kialakításának a tervezéssel és a kódminőséggel kapcsolatos vita elsődleges részévé kell válnia.

Tesztkód kezelése termékkódként

Ha kifejezetten azt állítja, hogy a tesztkód termékkód, egyértelművé teszi, hogy a tesztkód minősége ugyanolyan fontos a szállításhoz, mint a termékkódé. A teamsnek ugyanúgy kell kezelnie a tesztkódot, mint a termékkódot, és ugyanolyan szintű gondossággal kell kezelnie a tesztek és a tesztelési keretrendszerek tervezését és megvalósítását. Ez a munka hasonló a konfiguráció és az infrastruktúra kódként való kezeléséhez. A teljesség érdekében a kód áttekintésének figyelembe kell vennie a tesztkódot, és a termékkóddal megegyező minőségi sávon kell tartania.

Megosztott tesztinfrastruktúra használata

Csökkentse a küszöböt a tesztinfrastruktúra használatában, hogy megbízható minőségi jeleket generálhasson. Tekintsd a tesztelést az egész csapat megosztott szolgáltatásának. Tárolja az egységteszt kódot a termékkód mellett, és hozza létre a termékkel együtt. A buildelési folyamat részeként futtatott teszteknek olyan fejlesztői eszközökkel is futniuk kell, mint az Azure DevOps. Ha a tesztek a helyi fejlesztéstől az éles környezeten át minden környezetben futtathatók, ugyanolyan megbízhatóságúak, mint a termékkód.

A kódtulajdonosok felelőssé tétele a tesztelésért

A tesztkódnak a termékkód mellett kell lennie egy adattárban. Ha a kódot egy összetevő határán szeretné tesztelni, küldje el a tesztelés elszámoltathatóságát az összetevőkódot megíró személynek. Ne támaszkodjon másokra az összetevő teszteléséhez.

Esettanulmány: Balra váltás egységtesztekkel

Egy Microsoft-csapat úgy döntött, hogy az örökölt tesztcsomagokat modern DevOps egységtesztekre és egy korai tesztelési folyamatra cseréli. A csapat nyomon követte a háromhetes futamok előrehaladását az alábbi grafikonon látható módon. A grafikon 78-120 futamot fed le, amely 42 futamot jelöl 126 hét alatt, vagyis körülbelül két és fél évnyi erőfeszítést.

A csapat 27 000 örökölt teszttel indult a 78-as sprintben, és az S120-nál nulla örökölt tesztet ért el. A régi funkcionális tesztek többségét L0 és L1 egységtesztek halmaza váltotta fel. Az új L2-tesztek felváltották a tesztek egy részét, és a régi tesztek nagy része törölve lett.

Diagram, amely egy mintatesztportfólió-egyenleget jelenít meg az idő függvényében.

Egy olyan szoftveres folyamat során, amely több mint két évet vesz igénybe, sok mindent tanulhatunk magából a folyamatból. Összességében a tesztelési rendszer két év alatt történő teljes újrapróbálására tett erőfeszítések jelentős befektetésnek tették ki. Nem minden funkciócsapat végezte egyszerre a munkát. A szervezet számos csapata fektetett időt minden futamba, és néhány futamban ez volt a legtöbb, amit a csapat tett. Bár nehéz felmérni a műszak költségeit, ez a csapat minőségi és teljesítménycéljai szempontjából nem forgatható követelmény volt.

Kezdő lépések

Kezdetben a csapat egyedül hagyta el a régi funkcionális teszteket, az úgynevezett TRA-teszteket. A csapat azt szerette volna, hogy a fejlesztők elfogadják az egységtesztek írásának ötletét, különösen az új funkciókhoz tartozóak esetén. A fókusz az volt, hogy a lehető legegyszerűbb legyen az L0- és L1-tesztek készítése. A csapatnak először ki kellett fejlesztenie ezt a képességet, és lendületet kellett építenie.

Az előző grafikon azt mutatja, hogy az egységtesztek száma kezd korán növekedni, mivel a csapat az egységtesztek készítésének előnyeit látta. Az egységtesztek egyszerűbben karbantarthatók, gyorsabban futtathatók, és kevesebb hiba történt. Könnyű volt támogatást szerezni az összes egységteszt futtatásához a lekéréses kérelem folyamatában.

A csapat százegyedik sprintig nem az új L2-tesztek írására koncentrált. Eközben a TRA tesztek száma 27 000-ről 14 000-re csökkent Sprint 78-tól Sprint 101-ig. Az új egységtesztek felváltották a TRA-tesztek egy részét, de sokan egyszerűen törölve lettek a hasznosságuk csapatelemzése alapján.

A TRA-tesztek 2100-ról 3800-ra ugrottak a sprint 110-ben, mert több tesztet fedeztek fel a forrásfán, és hozzáadták a gráfhoz. Kiderült, hogy a tesztek mindig futottak, de nem voltak megfelelően nyomon követve. Ez nem válság volt, de fontos volt, hogy őszinte legyek, és szükség szerint újraértékeljük.

Gyorsulás

Miután a csapat folyamatos integrációs (CI) jelzést kapott, amely rendkívül gyors és megbízható volt, megbízhatóvá vált a termékminőség szempontjából. Az alábbi képernyőképen látható a lekéréses kérelem és a CI-folyamat működés közbeni állapota, valamint a különböző fázisokon való végiglépéshez szükséges idő.

Diagram, amely a pull requestet és a rolling CI pipeline működés közben mutatja be.

Körülbelül 30 percet vesz igénybe a pull request egyesítése, ami magában foglalja 60 000 egységteszt futtatását is. A kódegyesítéstől a CI-buildig körülbelül 22 perc. A CI első minőségi jelzése, a SelfTest körülbelül egy óra múlva érkezik. Ezután a termék nagy részét a javasolt módosítással tesztelik. Az egyesítéstől a SelfHostig két órán belül a teljes termék tesztelése történik, és a változás készen áll az éles üzemre.

Metrikák használata

A csapat az alábbi példához hasonlóan nyomon követi a scorecardot. Magas szinten a scorecard két metrikatípust követ nyomon: az állapotot vagy az adósságot, valamint a sebességet.

A tesztteljesítmény nyomon követésére szolgáló metrikák scorecardját ábrázoló diagram.

Az élő webhely állapotmetrikái esetében a csapat nyomon követi az észlelési időt, a mérséklés idejét, valamint azt, hogy a csapat hány javítási elemet hordoz. Javítási tételt a csapat egy élő webhely retrospektív elemzésében azonosít, hogy megelőzze a hasonló incidensek megismétlődését. A scorecard azt is nyomon követi, hogy a csapatok ésszerű időn belül bezárják-e a javítási elemeket.

A mérnöki állapotmetrikák esetében a csapat fejlesztőnként nyomon követi az aktív hibákat. Ha egy csapat fejlesztőnként ötnél több hibával rendelkezik, a csapatnak rangsorolnia kell ezeket a hibákat az új funkciók fejlesztése előtt. A csapat olyan speciális kategóriákban is nyomon követi az öregedési hibákat, mint a biztonság.

A mérnöki sebességmetrikák a folyamatos integrációs és folyamatos kézbesítési (CI/CD) folyamat különböző részeiben mérik a sebességet. A teljes cél a DevOps-folyamat sebességének növelése: egy ötlettől kezdve a kód éles környezetbe való beolvasása és az ügyfelektől érkező adatok fogadása.

Következő lépések