Az automatizált tesztek nem egy speciális eszköz a szoftverfejlesztők számára nagy projektekben. Az automatizált tesztek különösen a bővítményeknél segítenek a problémák gyors azonosításában. Segítenek abban, hogy a bővítmények zökkenőmentesen működjenek az újabb Joomla verziókban.
A Joomla Core fejlesztői azt akarják, hogy a külső szoftverfejlesztők teszteljék a bővítményeiket, hogy megtalálják a hibákat, mielőtt a felhasználó megtalálná őket. Ez sok időt igényel és unalmas munka. Ezért gyakran nem történik meg. Főleg nem, ha meg kell tenni manuálisan, emberek által minden új kiadáshoz. Az automatizált tesztelés lehetővé teszi a manuális lépések megismétlését minden kiadásnál anélkül, hogy egy ember maga hajtaná végre a lépéseket. Így a hibákat még azelőtt megtalálják, hogy a felhasználó az élő rendszerhez való hozzáféréskor találkozna velük.
Egyébként aki meg akarja nézni a Cypress-t, az jó kiindulópontnak találja ezt a szöveget. A problémákat anélkül tesztelheti, hogy mindent saját magának kellene telepítenie és konfigurálnia. A Joomla projekt Github tárházában minden készen áll.
Intro
"Bár igaz, hogy a minőséget nem lehet tesztelni, az ugyanilyen nyilvánvaló, hogy tesztelés nélkül lehetetlen minőséget fejleszteni." (James A. Whittaker)
Mielőtt először találkoztam a Cypress-szel, nem tudtam elképzelni, hogy a tesztelésemet gyakran akadályozó korlátok ténylegesen valamelyest félrekerülnek. Sok időt töltöttem a szoftverek tesztelésével – és korábban még több időt a problémák kezelésével amelyek a tesztelés hiánya miatt merültek fel! Most meg vagyok győződve arról, hogy a tesztek:
- a lehető legközelebb a programozáshoz,
- automatikusan,
- gyakran – ideális esetben minden programváltoztatás után
többet hozzon be, mint amennyibe kerül És mi több: a tesztelés még szórakoztató is lehet.
Érdemes a vizsgálati módszereket elsajátítani!A tesztmódszerek hosszú élettartamúak,mert nem csak bármilyen programozási nyelvvel használhatóak,szinte bármilyen emberi munkára alkalmazhatók.Az életben szinte mindent, ami fontos, egyszer érdemes kipróbálni. A tesztelési módszerek függetlenek az adott szoftvereszközöktől.Eltérően a programozási technikáktól vagy a programozási nyelvektől, amelyek gyakran divatosak és kimennek, a jó tesztek összeállításának ismerete időtlen.
Kinek kell elolvasnia ezt a szöveget?
Aki úgy gondolja, hogy a szoftvertesztelés időpocsékolás, nézze meg ezt a cikket. Külön szeretném felkérni azokat a fejlesztőket, hogy olvassák el, akik mindig is szerettek volna teszteket írni a szoftvereikhez - de soha nem tettek változatossá. A ciprus az ilyen akadályok eltávolításának egyik módja lehet.
Valami elmélet
A varázslatos háromszög
A Varázsháromszög leírja a költségek, a szükséges idő és az elérhető minőség közötti kapcsolatot.Eredetileg ezt a kapcsolatot a projektmenedzsmentben ismerték fel és írták le, de valószínűleg más területeken is hallott már erről a feszültségről. probléma szinte minden üzemben folyamatok egy vállalatban.
Például általában azt feltételezik, hogy a magasabb költség pozitív hatással van a minőségre és/vagy a befejezési dátumra, azaz az időre.
Fordítva, a költségmegtakarítás a minőség csökkenését és/vagy a befejezést késlelteti.
Most jön a varázslat: Leküzdjük az idő, a költségek és a minőség közötti összefüggést, mert hosszú távon ez is leküzdhető.
Az idő, a költségek és a minőség közötti kapcsolat hosszú távon leküzdhető.
Talán Ön is tapasztalta a gyakorlatban, hogy a minőség csökkenése hosszú távon nem jár költségmegtakarítással, az ebből eredő technikai adósság gyakran még költségnövekedéshez és időnövekedéshez is vezet.
A technikai adósság azt a többlet erőfeszítést jelenti, amely a nem jó programozott szoftverek módosításával és fejlesztésével jár a jól megírt szoftverekhez képest. Martin Fowler a következő típusú technikai adósságokat különbözteti meg: azokat, amelyeket szándékosan, és azokat, amelyeket véletlenül vállalt. Különbséget tesz körültekintő és meggondolatlan műszaki adósságok között is.
Költségek és előnyök
A szakirodalomban pusztító statisztikák találhatók a szoftverprojektek sikerének esélyeiről. Keveset változott az a negatív kép, amelyet már AW Feyhl 1990-es tanulmányában rögzített. Itt 50 szervezet 162 projektjének elemzésében , Meghatározták az eredeti tervezéshez képesti költségeltérést: a projektek 70%-a legalább 50%-os költségeltérést mutatott!Valami nem stimmel!Ezt ugye nem lehet csak úgy elfogadni?
Az egyik megoldás az lenne, ha teljesen mellőznénk a költségbecsléseket, és követnénk a #NoEstimates mozgalom érvelését . Ez a mozgalom azon a véleményen van, hogy a költségbecslések egy szoftverprojektben értelmetlenek. A szoftverprojekt a #NoEstimates véleménye szerint mindig tartalmazza a termelést Az új nem hasonlítható össze a már meglévő tapasztalatokkal, így nem is kiszámítható.
Minél több tapasztalatot szerzek, annál inkább arra a következtetésre jutok, hogy az extrém nézetek nem jók. A megoldás szinte mindig középen van. Kerülje a szélsőségeket szoftverprojekteknél is, és keresse a középutat. Nem kell 100%-os biztos terv. De nem szabad naivan új projektbe kezdeni. Bár a szoftver projektmenedzsment és különösen a költségbecslés fontos téma, ebben a szövegben nem fárasztom Önt ezzel tovább. A cikk középpontjában az E2E bemutatása áll. a tesztelés integrálható a szoftverfejlesztés gyakorlati munkafolyamatába.
Integrálja a szoftvertesztet a munkafolyamatba
Úgy döntött, hogy teszteli a szoftvert. Remek! Mikor van a legalkalmasabb idő erre? Vessünk egy pillantást a hibajavítás költségeire a projekt különböző fázisaiban. Minél korábban talál egy hibát, annál alacsonyabb a javítási költség .
Tesztelés és hibakeresés: Vannak olyan szavak, amelyeket gyakran ugyanabban a leheletben említenek, és amelyek jelentése ezért kiegyenlítődik. Közelebbről megvizsgálva azonban a kifejezések különböző értelmezéseket jelentenek. A tesztelés és a hibakeresés ezekhez a szavakhoz tartozik. A két kifejezés közös hogy észlelik a meghibásodásokat.. De a jelentésben is vannak eltérések.
- A tesztek a fejlesztés során ismeretlen meghibásodásokat találnak, a hiba feltárása költséges és költséges, a hiba lokalizálása és elhárítása olcsó.
- A hibakeresők a termék elkészülte után észlelt meghibásodásokat kijavítják, a hiba felderítése ingyenes, de a hiba felkutatása és kijavítása költséges.
Következtetés: A legésszerűbb a tesztek integrálását a lehető legkorábban elkezdeni, ezt sajnos nehéz megvalósítani egy olyan nyílt forráskódú projektben, mint a Joomla, többnyire önkéntes közreműködőkkel.
Folyamatos integráció (CI)
Tesztek folyamatos integrálása
Képzelje el a következő forgatókönyvet: Hamarosan megjelenik egy népszerű tartalomkezelő rendszer új verziója. Mindaz, amihez a csapat fejlesztői hozzájárultak a legutóbbi kiadás óta, most először használhatók együtt. Egyre nő a feszültség! működik? Sikeres lesz minden teszt – ha a projekt egyáltalán integrál teszteket.Vagy az új verzió megjelenését ismét el kell halasztani, és idegtépő órákig tartó hibajavítás vár ránk?A megjelenési dátum elhalasztása egyébként szintén nem jót tesz a szoftvertermék imázsának!Egy fejlesztő sem szereti átélni ezt a forgatókönyvet.Sokkal jobb bármikor tudni,hogy éppen milyen állapotban van a szoftverprojekt?A meglévőhöz nem illő kódot csak azután érdemes integrálni „igazságra készültek”.Különösen azokban az időkben, amikor egyre gyakoribb, hogy egy biztonsági hiányosságot ki kell javítani, egy projektnek mindig képesnek kell lennie egy kiadás létrehozására, és itt jön képbe a folyamatos integráció.
A folyamatos integráció során a szoftver egyes elemei tartósan integrálódnak A szoftver létrehozása és tesztelése kis ciklusokban történik Ily módon az integráció során problémákba, vagy hibás tesztekbe kerül a korai szakaszban, és nem napokkal vagy hetekkel később. Sikeres integráció esetén A hibaelhárítás sokkal egyszerűbb, mert a hibákat a programozás időpontjához közel fedezik fel, és általában a programnak csak egy kis részét érinti. A Joomla folyamatos integrációval integrálja az új kódot. Az új kódot csak akkor integrálja, ha minden teszt sikeresen sikeres.
Az új szoftverek folyamatos integrációjával a hibaelhárítás sokkal egyszerűbb, mivel a hibákat a programozáshoz közel fedezik fel, és általában csak a program egy kis részét érinti.
Annak érdekében, hogy a folyamatos integráció során mindig rendelkezésre álljon minden programrész tesztje, tesztvezérelt szoftvert kell fejlesztenie.
Tesztvezérelt fejlesztés (TDD)
A tesztvezérelt fejlesztés egy olyan programozási technika, amely kis lépésekben történő fejlesztést alkalmaz. Először meg kell írni a tesztkódot. Csak ezután kell létrehozni a tesztelendő programkódot. A program bármilyen módosítása csak azután történik meg, hogy az adott változtatáshoz tartozó tesztkód Létrehozva tehát a tesztjei azonnal meghiúsulnak a létrehozás után A szükséges függvény még nincs implementálva a programban Csak ezután hozza létre a tényleges programkódot - vagyis azt a programkódot, amelyik megfelel a tesztnek.
A TDD tesztek segítenek a program helyes megírásában .
Amikor először hall erről a technikáról, nem biztos, hogy elégedett a koncepcióval. Az „ember” mindig valami produktív dolgot akar először csinálni. A tesztek írása pedig első pillantásra nem tűnik produktívnak. Próbáld ki. Néha egy új technikával csak megismerés után barátkozik meg!A magas tesztlefedettségű projektekben kényelmesebben érzem magam, ha új funkciókat adok hozzá.
Ha végignézed a szöveg végén található gyakorlati részt, akkor kipróbálhatod. Először készítsd el a tesztet, majd írd meg a Joomla Core kódját. Utána küldj be mindent PR-ként a Githubon. Ha mindenki ezt tenné, a Joomla ideális tesztlefedettség lenne.
Viselkedésvezérelt fejlődés (BDD)
A BDD nem egy másik programozási technika vagy tesztelési technika, hanem egyfajta bevált gyakorlat a szoftverfejlesztéshez. A BDD ideálisan a TDD-vel együtt használható. A Behaviour-Driven-Development elvileg nem a programkód megvalósítását, hanem a végrehajtását teszteli. - azaz a program viselkedése Egy teszt ellenőrzi, hogy a specifikáció, azaz a vevői igény teljesül-e.
Amikor viselkedésvezérelt szoftvert fejleszt, a tesztek nemcsak a program helyes megírásában segítenek, hanem a megfelelő program megírásában is .
Mit értek ezen: "Írja meg a megfelelő programot"? Előfordul, hogy a felhasználók másképp látják a dolgokat, mint a fejlesztők. Példa a cikk törlésének munkafolyamata a Joomlában. Újra és újra találkozom olyan felhasználókkal, akik az állapotikonra kattintanak a kukába, és meglepődnek. A felhasználó általában intuitív módon azt feltételezi, hogy az elem immár végleg törölve van, de a kukába helyezettről aktiválásra vált. A fejlesztő számára az állapotikonra való kattintás állapotváltozást, váltást jelent. minden más nézetben. Miért legyen ez másképp a kukában?A fejlesztőnél hibamentesen implementálódik a funkció.A Joomla korrektül működik.De az én szememben ott a függvény nem a megfelelő,mert a legtöbb felhasználó egészen máshogy írná le /kérné .
A viselkedésvezérelt fejlesztésben a szoftverrel szemben támasztott követelmények példákon keresztül, az úgynevezett forgatókönyveken vagy felhasználói történeteken keresztül vannak leírva.
- a végfelhasználó erőteljes bevonása a szoftver fejlesztési folyamatába,
- a projekt összes fázisának dokumentálása felhasználói történetekkel/esetpéldákkal szöveges formában - általában a leírás nyelvén a Gherkin leíró nyelven,
- ezen felhasználói történetek/esettanulmányok automatikus tesztelése,
- egymást követő implementáció Így bármikor elérhető a megvalósítandó szoftver leírása A leírás segítségével folyamatosan biztosíthatja a már megvalósított programkód helyességét.
A Joomla projekt bevezette a BDD-t a Google Summer of Code projektjében . Azt remélték, hogy a programozási ismeretekkel nem rendelkező felhasználók könnyebben tudnak majd részt venni a Gherkin használatával . A megközelítést nem követték következetesen. Abban az időben a Joomla a Codecepciót használta. A Cypress segítségével a BDD fejlesztés BDD módon is fejleszthető.
Tervezés
Teszttípusok
- Egységtesztek: Az egységteszt olyan teszt, amely a legkisebb programegységeket önállóan teszteli.
- Integrációs tesztek: Az integrációs teszt olyan teszt, amely az egyes egységek kölcsönhatását teszteli.
- E2E tesztek vagy elfogadási tesztek: Egy elfogadási teszt ellenőrzi, hogy a program teljesíti-e az elején meghatározott feladatot.
Stratégiák
Ha új funkciót szeretne hozzáadni a Joomlához, és tesztekkel biztosítani szeretné, kétféleképpen járhat el.
A felülről lefelé és az alulról felfelé két alapvetően különböző megközelítés az összetett problémák megértéséhez és bemutatásához. A felülről lefelé haladva lépésről lépésre halad az absztrakttól és az általánostól a konkrét és konkrét felé. Hogy ezt egy példával illusztráljuk: Egy tartalomkezelő rendszer, mint a Joomla Általában böngészőben jeleníti meg a webhelyeket, de konkrétan számos apró részfeladat is van ebben a folyamatban, ezek egyike egy adott szöveg címsorban való megjelenítése.
Az alulról felfelé az ellenkező irányt írja le: ezen a ponton érdemes még egyszer megjegyezni, hogy a viselkedésvezérelt fejlesztés egyik eleme a szoftver viselkedésének szöveges leírásának elkészítése, amely az elfogadási kritériumok leírását segíti a tesztek elkészítésében - különösen a felső - szintű end-to-end tesztek vagy átvételi tesztek.
A tesztek elkészítésének manapság a szokásos megközelítése alulról történik. Ha a viselkedésvezérelt szoftverfejlesztést részesíti előnyben, akkor az ellenkező stratégiát kell alkalmaznia. A felülről lefelé irányuló stratégiát kell használnia. A felülről lefelé irányuló stratégiánál a félreértés korán felismerhető a tervezési fázisban.
-
Felülről lefelé irányuló tesztelés: A felülről lefelé irányuló stratégia alkalmazásakor az elfogadási tesztekkel kezdjük – vagyis a rendszer azon részével, amely a legszorosabban kapcsolódik a felhasználói igényekhez. . A hangsúly azon van, hogy teszteljük, hogyan kommunikál a felhasználó a rendszerrel. A felülről lefelé irányuló tesztelés hátránya, hogy sok időt kell tölteni tesztduplikátumok létrehozásával. A még nem integrált komponenseket helyőrzőkkel kell helyettesíteni. Az elején nincs valódi programkód, ezért a hiányzó részeket mesterségesen kell létrehozni, majd fokozatosan ezeket a mesterséges adatokat valóban kiszámított adatokkal pótolják.
-
Alulról felfelé irányuló tesztelés: Ha az alulról felfelé irányuló stratégiát követi, egységtesztekkel kezdi. Kezdetben a fejlesztő a célállapotot tartja szem előtt, de ezt követően először ezt a célt bontja le egyedi komponensekre. A probléma a Az alulról felfelé építkező megközelítés az, hogy nehéz tesztelni, hogy a későbbiekben egy komponens hogyan használható valós helyzetekben. Az alulról felfelé irányuló tesztelés előnye, hogy nagyon gyorsan elkészülünk a szoftverrészekkel, azonban ezeket a részeket óvatosan kell használni. Hibátlanul működnek, ezt biztosítják az egységtesztek, de nem biztos, hogy a végeredmény valóban olyan, mint amilyennek a vevő elképzeli a szoftvert.
Mike Cohn tesztpiramisa
Melyik teszttípusból hány tesztet kell végrehajtani? Mike Cohn tesztpiramisa az automatizált szoftvertesztek alkalmazásának koncepcióját írja le. A piramis három szintből áll, amelyek a használat gyakorisága és a relevancia szerint vannak felosztva.
Ideális esetben a tesztpiramis alapját sok gyors és könnyen karbantartható egységteszt képezi, így a legtöbb hiba gyorsan észlelhető.
A középső szinten az integrációs tesztek állnak, amelyek a kritikus interfészek célzott tesztelésére szolgálnak, az integrációs tesztek végrehajtási ideje hosszabb, karbantartásuk is bonyolultabb, mint az egységteszteké.
A piramis csúcsát a lassú E2E tesztek teszik ki, amelyek időnként sok karbantartást igényelnek.Az E2E tesztek nagyon hasznosak az alkalmazás teljes rendszerként történő teszteléséhez.
Követelmények
Milyen felszerelésre van szüksége a következő gyakorlati rész elvégzéséhez?
Milyen követelményeknek kell megfelelnie az alábbi gyakorlati részen aktívan dolgozni? Nem kell túl sok követelménynek megfelelnie ahhoz, hogy a kézikönyv tartalmán dolgozhasson. Természetesen számítógéppel kell rendelkeznie. Fejlesztői környezet Git-tel, A NodeJS-t és a Composert, valamint a helyi webszervert telepíteni vagy telepíteni kell rá.
Milyen tudással kell rendelkeznie személyesen?
Ismernie kell az alapvető programozási technikákat.Ideális esetben, ha már programozott egy kis webalkalmazást.Mindenesetre tudnia kell, hogy a fejlesztő számítógépén hol tárolja a fájlokat, és hogyan töltse be az internetböngészőbe.Új dolgokból.
Próbálja ki. Integrálja a teszteket a következő projektjébe. Talán az első teszt tapasztalata megkíméli Önt egy fárasztó hibakeresési munkamenettől vagy egy kínos hibától a valós rendszerben. Végül is a tesztekből álló biztonsági hálóval kevesebb költséggel fejleszthet szoftvert feszültség.
Felállítása
A Cypress beállítása a Joomla!
A Githubon elérhető fejlesztői verzióban a Joomla Cypress készen van konfigurálva. Vannak már tesztek, amelyeket útmutatóként használhatsz. Így nem szükséges mindent magadnak beállítani az első áttekintéshez. Így kísérletezhetsz a Cypress-szel , ismerje meg előnyeit és hátrányait, és döntse el maga, hogy kívánja-e használni a teszteszközt.
A helyi környezet beállításának lépései:
A lerakat klónozása a helyi webszerver gyökérkönyvtárába:
$ git clone https://github.com/joomla/joomla-cms.git
Keresse meg a joomla-cms mappát:
$ cd joomla-cms
A Joomla Roadmap szerint a következő nagyobb 5.0-s verzió 2023 októberében fog megjelenni. A naprakészen tartás érdekében itt ezt a fejlesztői verziót használom.
Váltás az 5.0-des ágra :
$ git checkout 5.0-dev
Telepítse az összes szükséges zeneszerző csomagot:
$ composer install
Telepítse az összes szükséges npm csomagot:
$ npm install
A munkaállomás beállításával kapcsolatos további információkért és segítségért olvassa el a Joomla dokumentációs cikket "A munkaállomás beállítása a Joomla fejlesztéshez" . A Cypressről a cypress.io webhelyen található információk . De ez jelenleg nem szükséges. A Joomla mindent beállít Csak be kell állítania az egyéni adatait a konfigurációs fájlon keresztül joomla-cms/cypress.config.js
.
Állítsa be az egyéni adatait. Ehhez használhatja a sablont joomla-cms/cypress.config.dist.js
tájékozódásként. Az én esetemben ez a fájl így néz ki:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
fixturesFolder: 'tests/cypress/fixtures',
videosFolder: 'tests/cypress/output/videos',
screenshotsFolder: 'tests/cypress/output/screenshots',
viewportHeight: 1000,
viewportWidth: 1200,
e2e: {
setupNodeEvents(on, config) {},
baseUrl: 'http://localhost/joomla-cms',
specPattern: [
'tests/cypress/integration/install/*.cy.{js,jsx,ts,tsx}',
'tests/cypress/integration/administrator/**/*.cy.{js,jsx,ts,tsx}',
'tests/cypress/integration/module/**/*.cy.{js,jsx,ts,tsx}',
'tests/cypress/integration/site/**/*.cy.{js,jsx,ts,tsx}'
],
supportFile: 'tests/cypress/support/index.js',
scrollBehavior: 'center',
browser: 'firefox',
screenshotOnRunFailure: true,
video: false
},
env: {
sitename: 'Joomla CMS Test',
name: 'admin',
email: Ez az e-mail-cím a szpemrobotok elleni védelem alatt áll. Megtekintéséhez engedélyeznie kell a JavaScript használatát. ',
username: 'admin',
password: 'adminadminadmin',
db_type: 'MySQLi',
db_host: 'mysql',
db_name: 'test_joomla',
db_user: 'root',
db_password: 'root',
db_prefix: 'j4_',
},
})
Konkrétan hozzáadtam a könyvtárat tests/cypress/integration/module/**/*.cy.{js,jsx,ts,tsx}
az specPattern
Array-hez, mert ott akarok később tesztet menteni a modulokhoz.Aztán megváltoztattam a felhasználónevet és a jelszavakat, mert szeretném manuálisan is tesztelni a telepítést és jobban megjegyezni a saját maguk által kiosztottakat. Docker konténert használok Ezért megváltoztattam az adatbázis-kiszolgálót és a hozzáférési adatokat, végül be kellett állítanom a http://localhost/joomla-cms
Joomla telepítésének gyökér URL-jét.
Használj Cypress-t
Webböngészőn keresztül
Hívjon npm run cypress:open
CLI-n keresztül a Joomla gyökérkönyvtárában. Kis idő múlva megnyílik a Cypress alkalmazás. Korábban létrehoztuk a fájlt. joomla-cms/cypress.config.dist.js
Hogy ez észlelhető, az abból látszik, hogy az E2E tesztelés konfigurálva van megadva.
Itt választhatja ki, hogy le akarja-e futtatni az E2E teszteket, és melyik böngészőt szeretné használni. A példához a "Tesztelés indítása Firefoxban" opciót választottam.
Az összes elérhető tesztcsomag megjelenik, és rákattinthat arra, amelyet futtatni szeretne. Amikor kiválaszt egy tesztcsomagot, a tesztek lefutnak, és a tesztek futását valós időben tekintheti meg a böngészőben.
Amíg a tesztek futnak, az egyik oldalon a végrehajtott szkript, a jobb oldalon pedig a böngészőben az eredmény látható, ezek nem csak képernyőképek, hanem a böngésző aktuális pillanatképei, így láthatja a tényleges HTML kódot. Képernyőképek, sőt videók is készíthetők a tesztekről.
Próbáld ki, ha úgy használod, hogy db_host: 'localhost',
teszteld a telepítést, és így helyesen konfiguráltad a Joomlát a szöveg következő részének munkájához.
Ha Ön, mint én, külső forrást használ (nem lcoalhost; én docker konténert használok), mint db_host
, akkor az ilyen telepítési teszt még nincs készen. Ebben az esetben a telepítési rutin biztonsági kérdése van, ami még nem vették figyelembe a tesztekben. Ebben az esetben manuálisan telepítse a Joomlát a fájlban megadott adatokkal joomla-cms/cypress.config.js
. A következő tesztek ebből a konfigurációs fájlból fogják használni a beállításokat, például a Joomla adminisztrációs területére való bejelentkezéshez. Így a teszt fejlesztője nem kell törődnie a bejelentkezési adatok megadásával, az egyező felhasználó és jelszó mindig automatikusan kerül felhasználásra a konfigurációs fájlból.
Fejetlen
Alapértelmezés szerint cypress run
az összes tesztet fej nélkül/joomla-cms/tests/cypress/output/screenshots
futtatja A következő parancs végrehajtja az összes már kódolt tesztet, és hiba esetén elmenti a képernyőképeket a könyvtárba . A kimeneti könyvtár be van állítva a cypress.config.js
fájlban.
$ npm run cypress:run
Egyéb CLI-parancsok
Vannak más hasznos parancsok is, amelyek a Joomla projektben nem szkriptként vannak implementálva , ezeket az npx-enpackage.json
keresztül hajtom végre [docs.npmjs.com/commands/npx].
ciprus ellenőrizni
A cypress verify
parancs ellenőrzi, hogy a Cypress megfelelően van-e telepítve és futtatható-e.
$ npx cypress verify
✔ Verified Cypress! /.../.cache/Cypress/12.8.1/Cypress
ciprus info
A cypress info
parancs információkat ad ki a Cypressről és az aktuális környezetről.
$ npx cypress info
Displaying Cypress info...
Detected 2 browsers installed:
1. Chromium
- Name: chromium
- Channel: stable
- Version: 113.0.5672.126
- Executable: chromium
- Profile: /.../snap/chromium/current
2. Firefox
- Name: firefox
- Channel: stable
- Version: 113.0.1
- Executable: firefox
- Profile: /.../snap/firefox/current/Cypress/firefox-stable
Note: to run these browsers, pass : to the '--browser' field
Examples:
- cypress run --browser chromium
- cypress run --browser firefox
Learn More: https://on.cypress.io/launching-browsers
Proxy Settings: none detected
Environment Variables: none detected
Application Data: /.../.config/cypress/cy/development
Browser Profiles: /.../.config/cypress/cy/development/browsers
Binary Caches: /.../.cache/Cypress
Cypress Version: 12.8.1 (stable)
System Platform: linux (Ubuntu - 22.04)
System Memory: 4.08 GB free 788 MB
ciprusos változat
A cypress version
parancs kinyomtatja a telepített Cypress bináris verziót, a Cypress csomag verzióját, a Cypress létrehozásához használt Electron verziót és a kötegelt csomópont verziót.
$ npx cypress version
Cypress package version: 12.8.1
Cypress binary version: 12.8.1
Electron version: 21.0.0
Bundled Node version: 16.16.0
A Cypress dokumentációja részletesebb információkat nyújt.
Az első saját teszt megírása
Ha eddig minden működött, elkezdhetjük saját tesztek készítését.
Szerezzen áttekintést
Tanulás a már kifejlesztett tesztekből
A Joomla CMS fejlesztői verziójában már vannak Cypress tesztek, ezek a mappában találhatók /tests/System/integration
, aki szeretne példával tanulni, itt talál egy megfelelő bemutatkozást.
Kód importálása ismétlődő feladatokhoz
A Joomla fejlesztői a Joomla-cypress NodeJs projekten dolgoznak , amely tesztkódot biztosít a gyakori tesztesetekhez, amelyeket a CMS fejlesztői verziójának telepítése során importálnak a következőn npm install
keresztül .
package.json
és a- támogatási fájl
/tests/System/support/index.js
A támogatási fájl a konfigurációban van megadvacypress.config.js
.
// package.json
{
"name": "joomla",
"version": "5.0.0",
"description": "Joomla CMS",
"license": "GPL-2.0-or-later",
"repository": {
"type": "git",
"url": "https://github.com/joomla/joomla-cms.git"
},
...
"devDependencies": {
...
"joomla-cypress": "^0.0.16",
...
}
}
Példa erre az eszköztár gombjára való kattintás, amely például az egyéni tesztekben elérhetővé Cypress.Commands.add('clickToolbarButton', clickToolbarButton)
teszi a parancsot , és egy kattintással szimulálja a parancsot. Az ehhez szükséges kódot az alábbi kódrészlet mutatja.clickToolbarButton()
cy.clickToolbarButton('new')
New
// node_modules/joomla-cypress/src/common.js
...
const clickToolbarButton = (button, subselector = null) => {
cy.log('**Click on a toolbar button**')
cy.log('Button: ' + button)
cy.log('Subselector: ' + subselector)
switch (button.toLowerCase())
{
case "new":
cy.get("#toolbar-new").click()
break
case "publish":
cy.get("#status-group-children-publish").click()
break
case "unpublish":
cy.get("#status-group-children-unpublish").click()
break
case "archive":
cy.get("#status-group-children-archive").click();
break
case "check-in":
cy.get("#status-group-children-checkin").click()
break
case "batch":
cy.get("#status-group-children-batch").click()
break
case "rebuild":
cy.get('#toolbar-refresh button').click()
break
case "trash":
cy.get("#status-group-children-trash").click()
break
case "save":
cy.get("#toolbar-apply").click()
break
case "save & close":
cy.get(".button-save").contains('Save & Close').click()
break
case "save & new":
cy.get("#save-group-children-save-new").click()
break
case "cancel":
cy.get("#toolbar-cancel").click()
break
case "options":
cy.get("#toolbar-options").click()
break
case "empty trash":
case "delete":
cy.get("#toolbar-delete").click()
break
case "feature":
cy.get("#status-group-children-featured").click()
break
case "unfeature":
cy.get("#status-group-children-unfeatured").click()
break
case "action":
cy.get("#toolbar-status-group").click()
break
case "transition":
cy.get(".button-transition.transition-" + subselector).click()
break
}
cy.log('--Click on a toolbar button--')
}
Cypress.Commands.add('clickToolbarButton', clickToolbarButton)
...
A következő kód egy másik példát mutat be, az adminisztrációs területre való bejelentkezést.
// /node_modules/joomla-cypress/src/user.js
...
const doAdministratorLogin = (user, password, useSnapshot = true) => {
cy.log('**Do administrator login**')
cy.log('User: ' + user)
cy.log('Password: ' + password)
cy.visit('administrator/index.php')
cy.get('#mod-login-username').type(user)
cy.get('#mod-login-password').type(password)
cy.get('#btn-login-submit').click()
cy.get('h1.page-title').should('contain', 'Home Dashboard')
cy.log('--Do administrator login--')
}
Cypress.Commands.add('doAdministratorLogin', doAdministratorLogin)
...
Gyakori feladatok az egyéni környezetben
A könyvtárban /tests/System/support
az egyes környezetekben gyakori feladatokat találja, amelyek könnyen újrafelhasználhatók, a támogatási fájlon keresztül importálják őket. A /tests/System/support/index.js
gyakran ismétlődő feladatra példa az adminisztrációs területre való bejelentkezés, amelyet a fájl kezel /tests/System/support/commands.js
funkció használatával doAdministratorLogin
.
A következő kód azt is megmutatja, hogy a konfigurációból származó információk hogyan cypress.config.js
kerülnek felhasználásra a tesztekben. csoporton belül Cypress.env('username')
hozzá van rendelve a tulajdonság értékéhez .username
env
Itt láthatjuk a parancsok felülírásának módját is, amely Cypress.Commands.overwrite('doAdministratorLogin' ...),
felülírja a csomagban látott kódot joomla-cypress
. Előnye, hogy a felhasználó és a jelszó automatikusan használatos az egyedi konfigurációból.
// /tests/System/support/commands.js
...
Cypress.Commands.overwrite('doAdministratorLogin', (originalFn, username, password, useSnapshot = true) => {
// Ensure there are valid credentials
const user = username ?? Cypress.env('username');
const pw = password ?? Cypress.env('password');
// Do normal login when no snapshot should be used
if (!useSnapshot) {
// Clear the session data
Cypress.session.clearAllSavedSessions();
// Call the normal function
return originalFn(user, pw);
}
// Do login through the session
return cy.session([user, pw, 'back'], () => originalFn(user, pw), { cacheAcrossSpecs: true });
});
...
Saját Joomla bővítmény telepítése
Annak érdekében, hogy lássuk, hogyan tesztelheti saját kódját, egy egyszerű példa komponenst telepítünk a Joomla háttérrendszeren keresztül. A telepítéshez szükséges fájl letölthető a Codeberg oldaláról .
A telepítés után a Joomla háttérprogram bal oldalsávjában talál egy hivatkozást a Foo komponens nézetére.
Most már beállítottunk egy tesztkörnyezetet és kódot a teszteléshez.
Az első saját teszt
Horgok
A backend tesztelésekor észre fogod venni, hogy minden tesztet bejelentkezéssel kell elindítani. Ezt a redundáns kódot a függvény használatával megakadályozhatjuk. beforeEach()
Ez az úgynevezett hook végrehajtja azt a kódot, amelyet minden teszt futtatása előtt beírunk. Innen a név beforeEach()
.
A Cypress többféle horogtípust kínál , beleértve before
a és after
horgokat, amelyek a tesztcsoport tesztjei előtt vagy után futnak, és beforeEach
és afterEach
horgokat, amelyek a csoport minden egyes tesztje előtt vagy után futnak. A horgokat globálisan vagy egy adott described
blokkon belül lehet meghatározni. A következő A fájlban található kódpélda azt eredményezi, hogy a blokkon tests/System/integration/administrator/components/com_foos/FoosList.cy.js
belüli minden egyes teszt előtt be kell jelentkezni a háttérben .described
test com_foos features
Most kezdjük a gyakorlati résszel, és tests/System/integration/administrator/components/com_foos/FoosList.cy.js
az első produktív teszt megírása előtt hozzuk létre a következő kódrészlettel a fájlt. Az első példánknak minden teszt előtt sikeresen be kell jelentkeznie a háttérbe! Ezt az első teszt létrehozása után teszteljük.
// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
describe('Test com_foos features', () => {
beforeEach(() => {
cy.doAdministratorLogin()
})
})
Megjegyzés: A fájlon belül megvalósított horgok /tests/System/support/index.js
a tesztruha minden tesztfájljára vonatkoznak.
Sikeres teszt
A tesztelésre telepített komponens a három elemet tartalmazza Astrid
, Nina
és Elmar
először teszteljük, hogy ezek az elemek sikeresek-e.
// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
describe('Test com_foos features', () => {
beforeEach(() => {
cy.doAdministratorLogin()
})
it('list view shows items', function () {
cy.visit('administrator/index.php?option=com_foos')
cy.get('main').should('contain.text', 'Astrid')
cy.get('main').should('contain.text', 'Nina')
cy.get('main').should('contain.text', 'Elmar')
cy.checkForPhpNoticesOrWarnings()
})
})
Megjegyzés: checkForPhpNoticesOrWarnings()
A fájlban található függvény /node_modules/joomla-cypress/src/support.js
.
A DOM elemet a Cypress getmain
paranccsal kapjuk meg
FooList.cy.js
Az imént létrehozott tesztet a bal oldalsávon található elérhető tesztek listájában kell megtalálnia . Ha nem ez a helyzet, kérjük, zárja be a böngészőt, és futtassa npm run cypress:open
újra.
Kattintson a teszt nevére a futtatáshoz, sikeresen befejeződik és zöld üzeneteket fog látni.
Sikertelen teszt
Adja hozzá a sort cy.get('main').should('contain.text', 'Sami')
a tesztfájlhoz, hogy a futás sikertelen legyen Nincs ilyen nevű elem A tesztfájl mentése után a Cypress észreveszi a változást Minden változtatás után a Cypress automatikusan újrafutja a tesztfájlban található összes tesztet.
// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
describe('Test com_foos features', () => {
beforeEach(() => {
cy.doAdministratorLogin()
})
it('list view shows items', function () {
cy.visit('administrator/index.php?option=com_foos')
cy.get('main').should('contain.text', 'Astrid')
cy.get('main').should('contain.text', 'Nina')
cy.get('main').should('contain.text', 'Elmar')
cy.get('main').should('contain.text', 'Sami')
cy.checkForPhpNoticesOrWarnings()
})
})
Ahogy az várható volt, a teszt sikertelen. Piros üzenetek jelennek meg. A bal oldalsávban minden tesztlépés kódja látható. Így meg lehet találni a hiba okát. Minden lépéshez van egy pillanatkép a HTML dokumentumról, így bármikor ellenőrizheti a jelölést. Ez különösen a fejlesztés során hasznos.
Futtasson csak egy tesztet egy fájlban
Demó kiterjesztésünk egynél több elrendezést tartalmaz. Adjon hozzá egy tesztet az üres állapotú elrendezés teszteléséhez. Mivel ebben a fájlban most két teszt van, a Cypress mindig mindkét tesztet lefutja minden alkalommal, amikor elmentjük a fájlt. Használhatjuk, hogy csak egy .only()
teszt végrehajtják:
// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
describe('Test com_foos features', () => {
beforeEach(() => {
cy.doAdministratorLogin()
})
it('list view shows items', function () {
cy.visit('administrator/index.php?option=com_foos')
cy.get('main').should('contain.text', 'Astrid')
cy.get('main').should('contain.text', 'Nina')
cy.get('main').should('contain.text', 'Elmar')
cy.checkForPhpNoticesOrWarnings()
})
it.only('emptystate layout', function () {
cy.visit('administrator/index.php?option=com_foos&view=foos&layout=emptystate')
cy.get('main').should('contain.text', 'No Foo have been created yet.')
})
})
A fejlesztés során ez nagyon kényelmes.
Speciális teszttulajdonságok
Most szeretnénk tesztelni az összetevőnk frontendjét, ezt egy külön fájlban tesszük meg /tests/System/integration/site/components/com_foos/FooItem.cy.js
.
Legtöbbször CSS-osztályt használunk, hogy elemeket szerezzünk be a Joomla tesztekben. Bár ez tökéletesen érvényes és működni fog, valójában nem ajánlott. Miért ne? Ha CSS-osztályokat vagy azonosítókat használ, a teszteket olyan dolgokhoz köti, amelyek nagy valószínűséggel idővel változni fog. Az osztályok és azonosítók a tervezést, az elrendezést és néha a JavaScript-en keresztüli vezérlést szolgálják, amely könnyen módosítható. Ha valaki megváltoztatja az osztály nevét vagy azonosítóját, a tesztek többé nem fognak működni. A tesztek kevésbé törékenyebbé és jövőbiztosabb, a Cypress azt javasolja, hogy speciális adatattribútumokat hozzon létre az elemekhez kifejezetten tesztelési célokra.
Az elemekhez az attribútumot fogom használni data-test
, először hozzáadom az attribútumot data-test="foo-main"
a gyártási kódhoz.
// /components/com_foos/tmpl/foo/default.php
\defined('_JEXEC') or die;
?>
<div data-test="foo-main">
Hello Foos
</div>
Ezután tesztelem a gyártási kódot az attribútum keresésével [data-test="foo-main"]
.
// tests/System/integration/site/components/com_foos/FooItem.cy.js
describe('Test com_foo frontend', () => {
it('Show frondend via query in url', function () {
cy.visit('index.php?option=com_foos&view=foo')
cy.get('[data-test="foo-main"]').should('contain.text', 'Hello Foos')
cy.checkForPhpNoticesOrWarnings()
})
})
Egy menüpont tesztelése és néhány gondolat az eseményekről, várakozásokról és bevált gyakorlatokról
Most szeretem tesztelni egy menüelem létrehozását a komponensünkhöz, ezt egy külön fájlban teszem meg /tests/System/integration/administrator/components/com_foos/MenuItem.cy.js
. Ez a kód összetett és sok speciális funkciót mutat.
Először definiáltam egy konstanst, amelyben a menüpont összes releváns tulajdonságát beállítom, ennek az az előnye, hogy egy releváns tulajdonság változása esetén csak egy helyen kell módosítanom:
const testMenuItem = {
'title': 'Test MenuItem',
'menuitemtype_title': 'COM_FOOS',
'menuitemtype_entry': 'COM_FOOS_FOO_VIEW_DEFAULT_TITLE'
}
Ezután megjelenik a fájl teljes kódja MenuItem.cy.js
:
// tests/System/integration/administrator/components/com_foos/MenuItem.cy.js
describe('Test menu item', () => {
beforeEach(() => {
cy.doAdministratorLogin(Cypress.env('username'), Cypress.env('password'))
})
it('creates a new menu item', function () {
const testMenuItem = {
'title': 'Test MenuItem',
'menuitemtype_title': 'COM_FOOS',
'menuitemtype_entry': 'COM_FOOS_FOO_VIEW_DEFAULT_TITLE'
}
cy.visit('administrator/index.php?option=com_menus&view=item&client_id=0&menutype=mainmenu&layout=edit')
cy.checkForPhpNoticesOrWarnings()
cy.get('h1.page-title').should('contain', 'Menus: New Item')
cy.get('#jform_title').clear().type(testMenuItem.title)
cy.contains('Select').click()
cy.get('.iframe').iframe('#collapse1-heading').contains(testMenuItem.menuitemtype_title).click()
cy.get('.iframe').iframe('#collapse1-heading').contains(testMenuItem.menuitemtype_entry).click()
cy.intercept('index.php?option=com_menus&view=items&menutype=mainmenu').as('item_list')
cy.clickToolbarButton('Save & Close')
cy.wait('@item_list')
cy.get('#system-message-container').contains('Menu item saved.').should('exist')
// Frontend
cy.visit('index.php')
cy.get('.sidebar-right').contains(testMenuItem.title).click()
cy.get('[data-test="foo-main"]').should('contain.text', 'Hello Foos')
cy.checkForPhpNoticesOrWarnings()
// Trash
cy.visit('administrator/index.php?option=com_menus&view=items&menutype=mainmenu')
cy.searchForItem(testMenuItem.title)
cy.checkAllResults()
cy.clickToolbarButton('Action')
cy.intercept('index.php?option=com_menus&view=items&menutype=mainmenu').as('item_trash')
cy.clickToolbarButton('trash')
cy.wait('@item_trash')
cy.get('#system-message-container').contains('Menu item trashed.').should('exist')
// Delete
cy.visit('administrator/index.php?option=com_menus&view=items&menutype=mainmenu')
cy.setFilter('published', 'Trashed')
cy.searchForItem(testMenuItem.title)
cy.checkAllResults()
cy.on("window:confirm", (s) => {
return true;
});
cy.intercept('index.php?option=com_menus&view=items&menutype=mainmenu').as('item_delete')
cy.clickToolbarButton('empty trash');
cy.wait('@item_delete')
cy.get('#system-message-container').contains('Menu item deleted.').should('exist')
})
})
- Ebben a kódban láthatsz egy példát arra, hogy tesztelsz valamit, majd mindent törölsz - így visszaállítod a kezdeti állapotot.Így a teszteket annyiszor ismételheted meg, ahányszor csak akarod. A kezdeti állapot visszaállítása nélkül a második teszt futás meghiúsul, mert a Joomla nem tárolhat két hasonló elemet.
Megjegyzés: A tesztnek a következőnek kell lennie:
- megismételhető.
- Ez konkrétan azt jelenti, hogy egy korlátozott problémát kell tesztelnie, és ennek kódja nem lehet túl terjedelmes.
- független más tesztektől.
- És láthatja, hogyan lehet a
cy.intercept()
[^docs.cypress.io/api/commands/intercept] paraméterrel definiált elfogott útvonalat álnévként használni, majd megvárni az álnévként meghatározott útvonalat a -valcy.wait()
.
Amikor teszteket írunk ilyen alkalmazásokhoz, az ember kísértést kelt, hogy véletlenszerű értékeket használjon, például
cy.wait(2000);
acy.wait
parancsban. A probléma ezzel a megközelítéssel az, hogy bár ez jól működhet a fejlesztés során. Nem garantált azonban, hogy mindig működik. Miért? Mert a mögöttes rendszer nehezen megjósolható dolgoktól függ, ezért mindig jobb, ha pontosan meghatározzuk, mire várunk.
- A kód azt is megmutatja, hogyan kell várni a riasztásra és megerősíteni azt.
cy.on("window:confirm", (s) => { return true; });
- Végül, de nem utolsósorban, a tesztkód Cypress beépített és Joomla-típusú funkciókat tartalmaz, amelyeket a bővítményfejlesztők újra felhasználhatnak, például olyan
cy.setFilter('published', 'Trashed')
funkciókatcy.clickToolbarButton('Save & Close')
, amelyekben általában megoldások találhatók az egyes tesztekre, és amelyekre különösen a Joomla fejlesztőknek van szükségük. .Aszinkron és szinkronkód keverése
A Cypress parancsok aszinkronok, vagyis nem értéket adnak vissza, hanem
generate
azt.A Cypress elindításakor nem hajtja végre azonnal a parancsokat, hanem sorosan beolvassa és sorba állítja.Ha a tesztekben kevered aszinkron és szinkron kódot, akkor váratlan eredményeket kaphat. Ha a következő kódot futtatja, akkor a várttól eltérően hibaüzenetet kap. Biztosan azt is várta volna, hogy azmainText = $main.text()
értéke megváltozikmainText
. DemainText === 'Initial'
a végén még mindig érvényes. Miért van ez? A Cypress először a szinkron kódot hajtja végre az elején és a végén.Csak akkor hívja meg a belső aszinkron résztthen()
, vagyismainText
inicializálja a változót és rögtön utána ellenőrzi, ha változott - ami persze nem így van.
let mainText = 'Initial'; cy.visit('administrator/index.php?option=com_foos&view=foos&layout=emptystate') cy.get("main").then( ($main) => (mainText = $main.text()) ); if (mainText === 'Initial') { throw new Error(`Der Text hat sich nicht geändert. Er lautet: ${mainText}`); }
A sor feldolgozása egészen áttekinthetővé és látványossá válik, ha a böngésző konzoljában megfigyeljük a következő kód végrehajtását: A 'Cypress Test.' szöveg már jóval az elem tartalmának megjelenítése előtt megjelenik, bár a
main
kódsorok más sorrendben.
cy.get('main').then(function(e){ console.log(e.text()) }) console.log('Cypress Test.')
Csonkok és kémek
Az A
stub
egy módszer a függvény viselkedésének szimulálására, amelytől a tesztek függenek. A tényleges függvény meghívása helyett a csonk lecseréli azt a függvényt, és egy előre definiált objektumot ad vissza. Általában egységtesztekben használják, de használható a végére is. - végpontig tesztelés.Az A
spy
hasonló a függvényhezstub
, de nem teljesen ugyanaz. Nem változtatja meg a függvény viselkedését, hanem úgy hagyja, ahogy van. Rögzít néhány információt a függvény meghívásának módjáról. Például annak ellenőrzésére, hogy a függvény meghívva van-e . a megfelelő paraméterekkel, vagy megszámolja, hogy milyen gyakran hívják a függvényt.A következő példa a
spy
és astub
működését mutatja. Az elemen keresztülconst stub = cy.stub()
létrehozzuk azstub
elemet, és a következő lépésben meghatározzuk, hogyfalse
az első hívásnál éstrue
a másodiknál melyik adható vissza. A használatával a használhatóvácy.on('window:confirm', stub)
tesszük a következőhöz. A következő lépésben létrehozzuk az elemmel , amely a hívását figyeli . Most azt teszteljük, hogy az első hívásnál a kategória törlése elutasításra kerül, a második hívásnál pedig megerősítésre kerül. Ezáltal biztosítja, hogy biztosan számíthatunk arra, hogy milyen visszatérési értékek lesznek szállítva van beágyazott. segít annak biztosításában, hogy a függvény valóban meghívásra került - és milyen gyakran hívták.stub
window:confirm'
cy.spy(win, 'confirm').as('winConfirmSpy')
Spy
'window:confirm'
stub
'window:confirm'
@winConfirmSpy
// tests/System/integration/administrator/components/com_foos/FoosList.cy.js ... const stub = cy.stub() stub.onFirstCall().returns(false) stub.onSecondCall().returns(true) cy.on('window:confirm', stub) cy.window().then(win => { cy.spy(win, 'confirm').as('winConfirmSpy') }) cy.intercept('index.php?option=com_categories&view=categories&extension=com_foos').as('cat_delete') cy.clickToolbarButton('empty trash'); cy.get('@winConfirmSpy').should('be.calledOnce') cy.get('main').should('contain.text', testFoo.category) cy.clickToolbarButton('empty trash'); cy.wait('@cat_delete') cy.get('@winConfirmSpy').should('be.calledTwice') cy.get('#system-message-container').contains('Category deleted.').should('exist') ...
Ha csak a hívás fix értékének beállításáról van szó
'window:confirm'
, akkor a következő kód elvégzi a feladatot.
cy.on("window:confirm", (s) => { return true; });
következtetés
Ebben a cikkben az E2E Cypress-szel való tesztelésének alapvető elméletét és gyakorlati jellemzőit ismerhette meg. A Joomla telepítésével bemutattam, hogyan kell különböző teszteket írni annak érdekében, hogy a webhelyen lévő Joomla összetevők az elvárásoknak megfelelően működjenek. Megmutattam a Cypress testreszabását is. Tesztelje a Runnert a cypress.json fájlban, és hogyan használhatja a testreszabott Cypress-parancsokat. Ezt könnyen követhető példák segítségével tette meg.
Remélem, hogy élvezte a Cypress-en keresztül a Joomlát példálózó körutat, és sok tudást és inspirációt tudtok elvenni maguknak.