Automatizované testy nejsou speciálním nástrojem pro vývojáře softwaru ve velkých projektech. Zejména u rozšíření jsou automatizované testy pomocí k rychlé identifikaci problémů, pomáhají zajistit bezproblémovou funkčnost rozšíření v novějších verzích Joomly.
Vývojáři Joomla Core chtějí, aby vývojáři softwaru třetích stran testovali jejich rozšíření a nacházeli chyby dříve, než je najde uživatel. To vyžaduje spoustu času a je to nudná práce. Proto se to často nedělá. Zvláště ne, pokud se to dělat musí manuálně lidmi pro každou novou verzi Automatizované testování umožňuje opakovat ruční kroky pro každou verzi, aniž by je člověk prováděl sám. Tímto způsobem jsou chyby nalezeny dříve, než se s nimi uživatel setká při přístupu k živému systému.
Mimochodem, každý, kdo se chce podívat na Cypress, najde tento text jako dobré místo, kde začít. Můžete testovat problémy, aniž byste museli vše sami instalovat a konfigurovat. V repozitáři Github projektu Joomla je vše připraveno.
Intro
„I když je pravda, že kvalitu nelze testovat, je stejně zřejmé, že bez testování není možné vyvinout nic kvalitního.“ – [James A. Whittaker]
Než jsem poprvé narazil na Cypress, nedokázal jsem si představit, že bariéry, které často překážely mému testování, budou skutečně poněkud posunuty stranou. Strávil jsem spoustu času testováním softwaru - a dříve ještě více času řešením problémů který vznikl kvůli nedostatku testování! Nyní jsem přesvědčen, že testy, které jsou:
- co nejblíže k naprogramování,
- automaticky,
- často – ideálně po každé změně programu,
přinést více, než kolik stojí A co víc: testování může být dokonce zábavné.
Testovací metody se vyplatí naučit!Testovací metody jsou dlouhodobé, protože je lze použít nejen s jakýmkoliv programovacím jazykem, ale lze je aplikovat téměř na jakoukoli lidskou práci, jednou za čas byste měli otestovat téměř vše důležité v životě. Testovací metody jsou nezávislé na konkrétních softwarových nástrojích.Na rozdíl od programovacích technik nebo programovacích jazyků, které jsou často v módě i mimo ni, je znalost, jak nastavit dobré testy, nadčasová.
Kdo by měl číst tento text?
Každý, kdo si myslí, že testování softwaru je ztráta času, by se měl podívat na tento článek. Zejména bych chtěl pozvat, aby si tento článek přečetli ty vývojáře, kteří vždy chtěli psát testy pro svůj software - ale nikdy to nedělali pro různé Cypřiš by mohl být způsob, jak tyto překážky odstranit.
Nějaká teorie
Magický trojúhelník
Magický trojúhelník popisuje vztah mezi náklady, požadovaným časem a dosažitelnou kvalitou. Původně byl tento vztah uznáván a popisován v projektovém řízení. Pravděpodobně jste však o tomto napětí slyšeli i v jiných oblastech. Problematika téměř ve všech provozních procesy ve firmě.
Obecně se například předpokládá, že vyšší náklady mají pozitivní dopad na kvalitu a/nebo datum dokončení – tedy čas.
Naopak úspora nákladů způsobí snížení kvality a/nebo zpoždění dokončení.
Nyní přichází do hry kouzlo: Překonáváme vztah mezi časem, náklady a kvalitou, protože z dlouhodobého hlediska to lze skutečně překonat.
Souvislost mezi časem, náklady a kvalitou lze dlouhodobě překonat.
Možná jste i vy v praxi zažili, že snížení kvality nevede v dlouhodobém horizontu k úspoře nákladů a technický dluh, který tím vzniká, často vede dokonce ke zvýšení nákladů a času navíc.
Technický dluh označuje mimořádné úsilí spojené s prováděním změn a vylepšení špatně naprogramovaného softwaru ve srovnání s dobře napsaným softwarem. Martin Fowler rozlišuje následující typy technického dluhu: ty, do kterých člověk vstoupil úmyslně, a ty, do kterých vstoupil neúmyslně Rozlišuje také mezi obezřetnými a lehkomyslnými technickými dluhy.
Náklady a přínosy
V literatuře najdete zdrcující statistiky o šancích na úspěch softwarových projektů. Málo se změnilo na negativním obrazu, který již zaznamenala studie AW Feyhla v 90. letech. Zde v analýze 162 projektů v 50 organizacích , byla stanovena odchylka nákladů oproti původnímu plánování: 70 % projektů vykazovalo odchylku nákladů alespoň 50 %! Něco není v pořádku! To nemůžete jen tak přijmout, že?
Jedním z řešení by bylo upustit od odhadů nákladů úplně a řídit se argumentací hnutí #NoEstimates . Toto hnutí zastává názor, že odhady nákladů v softwarovém projektu jsou nesmyslné. Softwarový projekt obsahuje podle názoru #NoEstimates vždy produkci něco nového. Nové není srovnatelné s již existujícími zkušenostmi, a proto není předvídatelné.
Čím více zkušeností získávám, tím více docházím k závěru, že extrémní názory nejsou dobré. Řešení je téměř vždy uprostřed. Vyhněte se extrémům i v softwarových projektech a hledejte střed. Nemusím mít 100% jistý plán. Ale také byste neměli naivně zakládat nový projekt. Přestože je řízení softwarových projektů a zejména odhad nákladů důležitým tématem, v tomto textu vás již nebudu nudit. Cílem tohoto článku je ukázat, jak E2E testování lze integrovat do praktického pracovního postupu vývoje softwaru.
Integrujte testování softwaru do svého pracovního postupu
Rozhodli jste se otestovat svůj software. Skvělé! Kdy je na to nejlepší čas? Pojďme se podívat na náklady na opravu chyby v různých fázích projektu. Čím dříve chybu objevíte, tím nižší budou náklady na její opravu. .
Testování a ladění: Existují slova, která jsou často zmiňována jedním dechem a jejichž významy jsou proto vyrovnány. Při bližším zkoumání však tyto termíny znamenají různé výklady. K těmto slovům patří testování a ladění. Tyto dva termíny mají společné že zjišťují poruchy.Jsou ale i rozdíly ve významu.
- Testy během vývoje naleznou neznámé poruchy, nalezení poruchy je drahé, lokalizace a odstranění chyby je levné.
- Debuggery opravují závady, které se najdou po dokončení produktu. Nalezení závady je bezplatné, ale lokalizace a oprava chyby je nákladná.
Závěr: Je nejrozumnější začít s integrací testů co nejdříve. Bohužel je to obtížné implementovat v open source projektu jako je Joomla s většinou dobrovolnými přispěvateli.
Průběžná integrace (CI)
Průběžná integrace testů
Představte si následující scénář. Chystá se vydání nové verze oblíbeného systému pro správu obsahu. Vše, čím vývojáři v týmu přispěli od posledního vydání, je nyní poprvé společně použito. funguje? Budou všechny testy úspěšné - jestli projekt vůbec zahrnuje testy. Nebo bude muset být vydání nové verze znovu odloženo a čekají nás nervy drásající hodiny oprav chyb? Mimochodem, odkládání data vydání také není dobré pro image softwarový produkt! Žádný vývojář nezažívá tento scénář rád. Je mnohem lepší kdykoli vědět, v jakém stavu se softwarový projekt aktuálně nachází? Kód, který nezapadá do stávajícího, by měl být integrován až poté, co byl „vyroben aby se vešly“.Zejména v dobách, kdy je stále běžnější, že je třeba opravit bezpečnostní mezeru, by měl být projekt vždy schopen vytvořit verzi! A zde přichází do hry průběžná integrace.
Při nepřetržité integraci jsou jednotlivé prvky softwaru trvale integrovány. Software je vytvářen a testován v malých cyklech. Tímto způsobem se setkáte s problémy při integraci nebo chybnými testy v rané fázi a ne o dny nebo týdny později. Odstraňování problémů je mnohem snazší, protože chyby jsou objeveny těsně před programováním a obvykle je ovlivněna pouze malá část programu Joomla integruje nový kód pomocí nepřetržité integrace Nový kód je integrován pouze tehdy, když projdou všechny testy.
Díky neustálé integraci nového softwaru je odstraňování problémů mnohem snazší, protože chyby jsou objeveny těsně před programováním a obvykle je ovlivněna pouze malá část programu.
Abyste zajistili, že budete mít během nepřetržité integrace neustále k dispozici testy pro všechny části programu, měli byste vyvinout testem řízený software.
Testem řízený vývoj (TDD)
Testem řízený vývoj je programovací technika, která využívá vývoj v malých krocích. Nejprve napíšete testovací kód. Teprve poté vytvoříte programový kód, který má být testován. Jakákoli změna programu je provedena až poté, co testovací kód pro tuto změnu Vaše testy selžou ihned po vytvoření. Požadovaná funkce ještě není v programu implementována. Teprve poté vytvoříte skutečný programový kód - tedy programový kód, který vyhovuje testu.
TDD testy vám pomohou napsat program správně .
Když poprvé uslyšíte o této technice, možná vám tento koncept nebude vyhovovat. „Člověk“ chce koneckonců vždy nejprve udělat něco produktivního. A psaní testů se na první pohled nezdá produktivní. Vyzkoušejte to. Někdy s novou technikou se spřátelíte až poté, co se s ní seznámíte! V projektech s vysokým pokrytím testů se cítím pohodlněji, když přidávám nové funkce.
Pokud si projdete cvičební část na konci textu, můžete si to vyzkoušet. Nejprve vytvořte test a poté napište kód pro Joomla Core. Poté vše společně odešlete jako PR na Github . Pokud by to udělal každý , Joomla bude mít ideální testovací pokrytí.
Vývoj řízený chováním (BDD)
BDD není další programovací technika nebo testovací technika, ale jakýsi osvědčený postup pro vývoj softwaru. BDD se ideálně používá společně s TDD. Behaviour-Driven-Development v zásadě znamená testování nikoli implementace programového kódu, ale provádění - tj. chování programu Test kontroluje, zda je splněna specifikace, tedy požadavek zákazníka.
Když vyvíjíte software způsobem řízeným chováním, testy vám nejen pomohou správně napsat program, ale také vám pomohou napsat správný program .
Co tím myslím: „Napiš správný program"? Stává se, že uživatelé vidí věci jinak než vývojáři. Příkladem je pracovní postup smazání článku v Joomle. Znovu a znovu se setkávám s uživateli, kteří kliknou na ikonu stavu v do koše a jsou překvapeni. Uživatel obvykle intuitivně předpokládá, že položka je nyní trvale smazána, ale je přepnuta z koše do aktivace. Pro vývojáře je kliknutí na ikonu stavu změnou stavu, přepnutím. ve všech ostatních zobrazeních. Proč by to mělo být v koši jinak? Pro vývojáře je funkce implementována bez chyb. Joomla funguje správně. Ale v mých očích funkce není na tom místě ta správná, protože většina uživatelů by ji popsala / požadovala docela jinak .
V Behavior Driven Development jsou požadavky na software popsány prostřednictvím příkladů nazývaných scénáře nebo uživatelské příběhy.
- silné zapojení koncového uživatele do procesu vývoje softwaru,
- dokumentaci všech fází projektu s uživatelskými příběhy/případy v textové podobě - obvykle v popisném jazyce v popisném jazyce Gherkin,
- automatické testování těchto uživatelských příběhů/případových studií,
- postupná implementace.Takže kdykoliv je přístupný popis implementovaného softwaru.Pomocí tohoto popisu můžete průběžně zajišťovat správnost již implementovaného programového kódu.
Projekt Joomla zavedl BDD v projektu Google Summer of Code . Doufalo se, že uživatelé bez znalosti programování se budou moci snadněji zapojit pomocí Gherkin ). Tento přístup nebyl důsledně dodržován. V té době Joomla používala Codeception jako S Cypressem je také možné vyvíjet vývoj BDD způsobem BDD.
Plánování
Typy testů
- Unit testy: Unit test je test, který nezávisle testuje nejmenší programové jednotky.
- Integrační testy: Integrační test je test, který testuje interakci jednotlivých jednotek.
- E2E testy nebo akceptační testy: Akceptační test kontroluje, zda program plní úlohu definovanou na začátku.
Strategie
Pokud chcete v Joomle přidat novou funkci a zabezpečit ji testy, můžete postupovat dvěma způsoby.
Top-down a bottom-up jsou dva zásadně odlišné přístupy k pochopení a prezentaci složitých problémů. Top-down jde krok za krokem od abstraktního a obecného ke konkrétnímu a konkrétnímu. Pro ilustraci na příkladu: Systém pro správu obsahu jako Joomla obecně prezentuje webové stránky v prohlížeči, konkrétně však v tomto procesu existuje řada drobných dílčích úkolů, jedním z nich je zobrazení konkrétního textu v nadpisu.
Bottom-up popisuje opačný směr: na tomto místě je vhodné si ještě jednou připomenout, že jedním z prvků behaviorálně řízeného vývoje je vytvoření textového popisu chování softwaru.Tento popis akceptačních kritérií pomáhá vytvářet testy – zejména horní -úrovňové end-to-end testy nebo akceptační testy.
Obvyklý přístup k vytváření testů je dnes zdola. Pokud dáváte přednost vývoji softwaru řízenému chováním, měli byste použít opačnou strategii. Měli byste použít strategii shora dolů. Při strategii shora dolů je nedorozumění identifikováno brzy ve fázi návrhu.
-
Testování shora dolů: Při aplikaci strategie shora dolů se začíná akceptačními testy - tedy tou částí systému, která je nejtěsněji spojena s požadavky uživatele. U softwaru napsaného pro lidské uživatele je to obvykle uživatelské rozhraní. . Důraz je kladen na testování toho, jak uživatel interaguje se systémem. Nevýhodou testování shora dolů je, že je třeba věnovat mnoho času vytváření testovacích duplikátů. Komponenty, které ještě nejsou integrované, musí být nahrazeny zástupnými symboly. Na začátku není skutečný programový kód, chybějící části se proto musí vytvářet uměle a postupně se tato umělá data nahrazují skutečně vypočítanými daty.
-
Testování zdola nahoru: Pokud se budete řídit strategií zdola nahoru, začnete s testy jednotek. Na začátku má vývojář na mysli cílový stav. Tento cíl však nejprve rozloží na jednotlivé komponenty. Problém s Přístup zdola nahoru spočívá v tom, že je obtížné otestovat, jak bude komponenta později využita v reálných situacích. Výhodou testování zdola nahoru je, že softwarové části máme hotové velmi rychle. Tyto části je však třeba používat opatrně. Fungují správně. To je to, co zajišťují testy jednotek. Ale zda je konečný výsledek skutečně takový, jak si zákazník software představuje, není zaručeno.
Testovací pyramida od Mikea Cohna
Kolik testů kterého typu testu by mělo být implementováno? Testovací pyramida Mikea Cohna popisuje koncept využití automatizovaných softwarových testů. Pyramida se skládá ze tří úrovní, strukturovaných podle frekvence použití a relevance.
V ideálním případě je základ testovací pyramidy tvořen mnoha rychlými a snadno udržovatelnými jednotkovými testy, čímž lze rychle odhalit většinu chyb.
Na střední úrovni jsou integrační testy, které poskytují služby pro cílené testování kritických rozhraní, doby provádění integračních testů jsou delší a jejich údržba je také složitější než u unit testů.
Vrchol pyramidy tvoří pomalé E2E testy, které někdy vyžadují velkou údržbu.E2E testy jsou velmi užitečné pro testování aplikace jako kompletního systému.
Požadavky
Jaké vybavení potřebujete pro práci na následující praktické části?
Jaké požadavky máte na aktivní práci na následující praktické části Nemusíte splňovat příliš mnoho požadavků, abyste mohli pracovat na obsahu této příručky Samozřejmě musíte mít počítač Vývojové prostředí s Git, NodeJS a Composer a místní webový server by na něm měly být nainstalovány nebo instalovatelné.
Jaké znalosti byste měli mít vy osobně?
Měli byste znát základní techniky programování, v ideálním případě již máte naprogramovanou malou webovou aplikaci, v každém případě byste měli vědět, kam soubory na vývojovém počítači ukládat a jak je načítat do internetového prohlížeče, nové věci.
Vyzkoušejte to. Integrujte testy do svého dalšího projektu. Možná vám vaše první zkušenost s testem ušetří zdlouhavé ladění nebo trapnou chybu ve skutečném systému. Koneckonců, s bezpečnostní sítí testů můžete vyvíjet software s méně stres.
Nastavení
Nastavení Cypress s Joomla!
Ve vývojářské verzi dostupné na Github je Joomla nakonfigurovaná pro Cypress ready. Existují již testy, které můžete použít jako vodítko. Není tedy nutné vše nastavovat sami, abyste získali první přehled. Tímto způsobem můžete experimentovat s Cypress , seznamte se s jeho výhodami a nevýhodami a sami se rozhodněte, zda chcete testovací nástroj používat.
Kroky k nastavení místního prostředí:
Naklonujte úložiště do kořenového adresáře vašeho místního webového serveru:
$ git clone https://github.com/joomla/joomla-cms.git
Přejděte do složky joomla-cms:
$ cd joomla-cms
Podle Joomla Roadmap bude další hlavní verze 5.0 vydána v říjnu 2023. Abych byl aktuální, používám zde tuto vývojovou verzi.
Změna na větev 5.0-dev :
$ git checkout 5.0-dev
Nainstalujte všechny potřebné balíčky skladatelů:
$ composer install
Nainstalujte všechny potřebné balíčky npm:
$ npm install
Další informace a pomoc s nastavením vaší pracovní stanice najdete v článku dokumentace k Joomle „Nastavení vaší pracovní stanice pro vývoj Joomly“ . Pro Cypress jsou informace na cypress.io . Ale to v tuto chvíli není nutné. Joomla nastaví vše Stačí nastavit vaše individuální údaje prostřednictvím konfiguračního souboru joomla-cms/cypress.config.js
.
Nastavte si svá individuální data. K tomu můžete použít šablonu joomla-cms/cypress.config.dist.js
jako orientaci. V mém případě tento soubor vypadá takto:
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: Tato e-mailová adresa je chráněna před spamboty. Pro její zobrazení musíte mít povolen Javascript. ',
username: 'admin',
password: 'adminadminadmin',
db_type: 'MySQLi',
db_host: 'mysql',
db_name: 'test_joomla',
db_user: 'root',
db_password: 'root',
db_prefix: 'j4_',
},
})
Konkrétně jsem přidal adresář tests/cypress/integration/module/**/*.cy.{js,jsx,ts,tsx}
do specPattern
Array, protože tam chci později uložit test pro moduly. Pak jsem změnil uživatelské jméno a hesla, protože chci instalaci otestovat ručně a lépe si zapamatovat ty, které si sami přiřadili. Používám kontejner Docker jako databáze.Proto jsem změnil databázový server a přístupové údaje.A nakonec jsem musel nastavit kořenovou URL http://localhost/joomla-cms
mé instalace Joomly.
Použijte Cypress
Prostřednictvím webového prohlížeče
Zavolejte npm run cypress:open
přes CLI ve vašem kořenovém adresáři Joomla. Krátce nato se otevře aplikace Cypress. Již dříve jsme vytvořili soubor . joomla-cms/cypress.config.dist.js
Že je detekován, je patrné ze skutečnosti, že E2E Testing je specifikován jako nakonfigurovaný.
Zde si můžete vybrat, zda chcete spouštět testy E2E a jaký prohlížeč chcete použít, pro příklad jsem zvolil možnost „Zahájit testování ve Firefoxu“.
Zobrazí se seznam všech dostupných testovacích sad a vy můžete kliknout na tu, kterou chcete spustit.Když vyberete testovací sadu, testy se spustí a průběh testů si můžete prohlédnout v reálném čase v prohlížeči.
Zatímco testy běží, můžete na jedné straně vidět spuštěný skript a na pravé straně výsledek v prohlížeči. Nejedná se pouze o snímky obrazovky, ale o skutečné snímky prohlížeče v danou chvíli, takže můžete vidět skutečný HTML kód Jsou také možné snímky obrazovky a dokonce i videa z testů.
Vyzkoušejte.Pokud používáte jako, db_host: 'localhost',
můžete otestovat instalaci a tím správně nakonfigurovat Joomlu pro práci v následující části tohoto textu.
Pokud jako já používáte externí zdroj (ne lcoalhost; používám docker kontejner) jako db_host
, test pro tento druh instalace ještě není připraven. V takovém případě je otázka bezpečnosti v instalační rutině, která je zatím není v testech uvažováno. V tomto případě nainstalujte Joomlu ručně s informacemi zadanými v souboru joomla-cms/cypress.config.js
. Následující testy použijí nastavení z tohoto konfiguračního souboru, například pro přihlášení do administrační oblasti Joomly. Tímto způsobem vývojář testu provede nemusí se starat o zadávání přihlašovacích údajů.Shodující se uživatel a heslo se vždy automaticky použije z konfiguračního souboru.
Bezhlavý
Ve výchozím nastavení cypress run
spouští všechny testy bezhlavě/joomla-cms/tests/cypress/output/screenshots
Následující příkaz provede všechny již nakódované testy a v případě chyby uloží snímky obrazovky do adresáře Výstupní adresář byl nastaven v cypress.config.js
souboru.
$ npm run cypress:run
Další příkazy CLI
Existují další užitečné příkazy, které nejsou implementovány jako skripty v package.json
projektu Joomla, spouštím je přes npx [docs.npmjs.com/commands/npx].
cypřiš ověřit
Příkaz cypress verify
ověří, zda je Cypress správně nainstalován a lze jej spustit.
$ npx cypress verify
✔ Verified Cypress! /.../.cache/Cypress/12.8.1/Cypress
informace o cypřiši
Výstupem příkazu cypress info
jsou informace o Cypressu a aktuálním prostředí.
$ 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
cypřišovou verzi
Příkaz cypress version
vytiskne nainstalovanou binární verzi Cypress, verzi balíčku Cypress, verzi Electronu použitou k vytvoření Cypress a verzi přibaleného uzlu.
$ 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
Dokumentace Cypress poskytuje podrobnější informace.
Psaní prvního vlastního testu
Pokud vše doposud fungovalo, můžeme začít vytvářet vlastní testy.
Získejte přehled
Učení z již vyvinutých testů
Ve vývojové verzi redakčního systému Joomla jsou již Cypress testy, které jsou ve složce Ti, /tests/System/integration
kteří se rádi učí na příkladu, zde najdou vhodný úvod.
Importujte kód pro opakující se úkoly
Vývojáři Joomly pracují na projektu NodeJs joomla-cypress , který poskytuje testovací kód pro běžné testovací případy. Tyto jsou importovány během instalace vývojářské verze CMS npm install
pomocí
package.json
a prostřednictvím- soubor podpory
/tests/System/support/index.js
Soubor podpory je definován v konfiguracicypress.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říkladem je kliknutí na tlačítko na panelu nástrojů. Například Cypress.Commands.add('clickToolbarButton', clickToolbarButton)
způsobí, že příkaz clickToolbarButton()
bude dostupný ve vlastních testech a cy.clickToolbarButton('new')
kliknutím na tlačítko New
se simuluje. Kód, který je k tomu zapotřebí, je uveden v kódu níže.
// 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)
...
Následující kód ukazuje další příklad, přihlášení do administrační oblasti.
// /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)
...
Běžné úkoly v individuálním prostředí
V adresáři /tests/System/support
naleznete běžné úlohy v jednotlivých prostředích, aby je bylo možné snadno znovu použít, importují se přes soubor podpory /tests/System/support/index.js
Příkladem často se opakující úlohy je přihlášení do administrační oblasti, které je řešeno v souboru /tests/System/support/commands.js
pomocí funkce doAdministratorLogin
.
cypress.config.js
Následující kód také ukazuje, jak se v testech používají informace z konfigurace. Cypress.env('username')
je přiřazena hodnota vlastnosti username
v rámci skupiny env
.
Také zde vidíme, jak přepsat příkazy Cypress.Commands.overwrite('doAdministratorLogin' ...),
přepíše kód, který jsme právě viděli v balíčku.Výhodou joomla-cypress
je, že uživatel a heslo jsou automaticky použity z individuální konfigurace.
// /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 });
});
...
Nainstalujte si vlastní rozšíření Joomla
Abychom viděli, jak otestovat svůj vlastní kód, nainstalujeme jednoduchou ukázkovou komponentu přes backend Joomla Soubor pro instalaci lze stáhnout z Codeberg .
Po instalaci najdete odkaz na pohled na komponentu Foo v levém postranním panelu backendu Joomly.
Nyní máme nastavené testovací prostředí a kód pro testování.
První vlastní test
Háčky
Při testování backendu si všimnete, že každý test musíte spouštět přihlášením.Tomuto nadbytečnému kódu můžeme zabránit pomocí funkce beforeEach()
Tento tzv. hook spustí kód, který zadáme před spuštěním každého testu.Odtud název beforeEach()
.
Cypress nabízí několik typů háčků , včetně háčků before
a after
háčků, které běží před nebo po testech v testovací skupině, a beforeEach
háčků afterEach
, které se spouštějí před každým jednotlivým testem ve skupině nebo po něm. Háčky lze definovat globálně nebo v rámci konkrétního described
bloku. Další příklad kódu v souboru způsobí, že se v backendu před každým testem v rámci bloku tests/System/integration/administrator/components/com_foos/FoosList.cy.js
provede přihlášení .described
test com_foos features
Nyní začneme praktickou částí a vytvoříme soubor tests/System/integration/administrator/components/com_foos/FoosList.cy.js
s dalším kódem odstřiženým před napsáním prvního produktivního testu. Náš první příklad by nás měl úspěšně přihlásit do backendu před jakýmkoli testem! Otestujeme to po vytvoření prvního testu.
// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
describe('Test com_foos features', () => {
beforeEach(() => {
cy.doAdministratorLogin()
})
})
Poznámka: Háčky, které jsou implementovány v souboru /tests/System/support/index.js
, se vztahují na každý testovací soubor v testovacím obleku.
Úspěšný test
Komponenta, kterou jsme nainstalovali pro testování, obsahuje tři prvky Astrid
a Nina
. Elmar
Nejprve otestujeme, zda byly tyto prvky úspěšně vytvořeny.
// 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()
})
})
Poznámka: Funkce, checkForPhpNoticesOrWarnings()
kterou najdete v souboru /node_modules/joomla-cypress/src/support.js
.
Prvek DOM získáme main
přes Cypress příkaz get
Váš právě vytvořený test byste měli najít FooList.cy.js
v seznamu dostupných testů v levém postranním panelu. Pokud tomu tak není, zavřete prohlížeč a spusťte jej npm run cypress:open
znovu.
Klikněte na název testu pro jeho spuštění, měl by skončit úspěšně a uvidíte zelené zprávy.
Neúspěšný test
Přidejte řádek cy.get('main').should('contain.text', 'Sami')
do testovacího souboru, aby běh selhal Neexistuje žádný prvek s tímto názvem Po uložení testovacího souboru Cypress zaznamená změnu Po každé změně Cypress automaticky znovu spustí všechny testy v testovacím souboru.
// 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()
})
})
Podle očekávání se test nezdařil. Jsou zde červené zprávy. Kód každého testovacího kroku vidíte v levém postranním panelu. Je tedy možné najít důvod chyby. Ke každému kroku je k dispozici snímek HTML dokumentu, takže můžete značky kdykoli zkontrolovat. To je užitečné, zejména během vývoje.
Spusťte pouze jeden test v souboru
Naše demo rozšíření obsahuje více než jedno rozvržení. Přidejte test pro testování rozvržení prázdného stavu. Protože nyní máme v tomto souboru dva testy, Cypress vždy spustí oba testy při každém uložení souboru. Můžeme použít tak, že pouze jeden .only()
test se provádí:
// 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.')
})
})
Během vývoje je to velmi pohodlné.
Speciální testovací atributy
Nyní bychom rádi otestovali frontend pro naši komponentu, a to v samostatném souboru /tests/System/integration/site/components/com_foos/FooItem.cy.js
.
Většinu času používáme třídu CSS k získání prvků v testech Joomla. I když je to dokonale platné a bude to fungovat, ve skutečnosti se to nedoporučuje. Proč ne? Když používáte třídy CSS nebo ID, svážete své testy s věcmi, které se s největší pravděpodobností časem změní. Třídy a ID slouží k návrhu, rozvržení a někdy prostřednictvím JavaScriptu pro ovládání, které se může snadno změnit. Pokud někdo změní název třídy nebo ID, vaše testy již nebudou fungovat. Aby vaše testy byly méně křehké a Cypress doporučuje vytvořit speciální datové atributy pro vaše prvky speciálně pro účely testování.
Atribut použiji data-test
pro prvky Nejprve přidám atribut data-test="foo-main"
do výrobního kódu.
// /components/com_foos/tmpl/foo/default.php
\defined('_JEXEC') or die;
?>
<div data-test="foo-main">
Hello Foos
</div>
Poté otestuji produkční kód hledáním atributu [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()
})
})
Testování položky nabídky a několik myšlenek na události, čekání a osvědčené postupy
Nyní bych rád otestoval vytvoření položky nabídky pro naši komponentu. Dělám to v samostatném souboru /tests/System/integration/administrator/components/com_foos/MenuItem.cy.js
. Tento kód je složitý a ukazuje spoustu speciálních funkcí.
Nejprve jsem si definoval konstantu, ve které nastavuji všechny relevantní vlastnosti položky menu, což má tu výhodu, že v případě změny příslušné vlastnosti musím upravovat pouze na jednom místě:
const testMenuItem = {
'title': 'Test MenuItem',
'menuitemtype_title': 'COM_FOOS',
'menuitemtype_entry': 'COM_FOOS_FOO_VIEW_DEFAULT_TITLE'
}
Dále uvidíte celý kód souboru 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')
})
})
- V tomto kódu můžete vidět příklad testování něčeho a následného smazání všeho - tedy obnovení počátečního stavu. Tímto způsobem můžete testy opakovat, kolikrát chcete. Bez obnovení počátečního stavu se druhé testovací spuštění nezdaří, protože Joomla nelze uložit dva podobné prvky.
Poznámka: Test by měl být:
- opakovatelný.
- Konkrétně to znamená, že by měl testovat omezený problém a kód pro to by neměl být příliš rozsáhlý.
- nezávislé na jiných testech.
- A můžete vidět, jak použít zachycenou trasu definovanou pomocí
cy.intercept()
[^docs.cypress.io/api/commands/intercept] jako alias, a pak počkat na trasu definovanou jako alias pomocícy.wait()
.
Při psaní testů pro takové aplikace jsme v pokušení používat náhodné hodnoty, například
cy.wait(2000);
vcy.wait
příkazu. Problém tohoto přístupu je, že i když to může fungovat dobře ve vývoji. Není však zaručeno, že bude fungovat vždy. Proč? Protože základní systém závisí na věcech, které je těžké předvídat, proto je vždy lepší přesně definovat, na co čekáte.
- Kód také ukazuje, jak čekat na upozornění a potvrdit jej.
cy.on("window:confirm", (s) => { return true; });
- V neposlední řadě obsahuje testovací kód vestavěný Cypress a funkce typické pro Joomlu, které mohou vývojáři rozšíření znovu použít. Například nebo jsou to funkce,
cy.setFilter('published', 'Trashed')
vecy.clickToolbarButton('Save & Close')
kterých lze obecně najít řešení pro jednotlivé testy a které zejména vývojáři Joomly často potřebují .Míchání asynchronního a synchronizačního kódu
Příkazy Cypress jsou asynchronní, to znamená, že nevrací hodnotu, ale
generate
ona Když spustíme Cypress, neprovede příkazy okamžitě, ale čte je sériově a řadí je do fronty Pokud v testech namícháte asynchronní a synchronní kód, může získat neočekávané výsledky. Pokud spustíte následující kód, dostanete proti očekávání chybu. Určitě byste také očekávali, žemainText = $main.text()
změní hodnotu . Na konci jemainText
však stále platný. Proč? Cypress nejprve spustí synchronní kód namainText === 'Initial'
na začátku a na konci.Teprve pak zavolá asynchronní část inside.Tothen()
znamená,že se proměnnámainText
inicializuje a hned poté se zkontroluje,zda se změnila -což samozřejmě není tento případ.
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}`); }
Zpracování fronty se stává zcela jasným a vizuálním, pokud pozorujete provádění následujícího kódu v konzole prohlížeče. Text 'Cypress Test.' se objeví dlouho před zobrazením obsahu prvku, ačkoli řádky kódu
main
jsou v jiném pořadí.
cy.get('main').then(function(e){ console.log(e.text()) }) console.log('Cypress Test.')
Pahýly a špióni
A
stub
je způsob, jak simulovat chování funkce, na které testy závisí. Namísto volání skutečné funkce stub tuto funkci nahradí a vrátí předdefinovaný objekt. Obvykle se používá v jednotkových testech, ale může být také použit pro ukončení - testování do konce.A
spy
je podobnéstub
, ale není úplně stejné. Nemění chování funkce, ale ponechává ji tak, jak je. Zachycuje některé informace o tom, jak se funkce volá. Například pro kontrolu, zda je funkce volána se správnými parametry nebo spočítat, jak často je funkce volána.Následující příklad ukazuje a
spy
a astub
v akci. Přesconst stub = cy.stub()
vytvořímestub
prvek a v dalším kroku určíme, kterýfalse
se vrátí pro první volání a protrue
druhé. Pomocícy.on('window:confirm', stub)
udělámestub
be use forwindow:confirm'
. V dalším kroku vytvoříme scy.spy(win, 'confirm').as('winConfirmSpy')
prvkemSpy
, který sleduje volání'window:confirm'
. Nyní testujeme, že při prvním volání je smazání kategorie odmítnuto a při druhém volání je potvrzeno. Tím zajistíme,stub
že můžeme s jistotou očekávat, jaké budou návratové hodnoty dodaná.'window:confirm'
je zapouzdřena@winConfirmSpy
pomáhá zajistit, že funkce byla skutečně volána – a jak často byla volána.
// 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') ...
Pokud se jedná pouze o nastavení pevné hodnoty pro volání
'window:confirm'
, následující kód to udělá.
cy.on("window:confirm", (s) => { return true; });
závěr
V tomto článku jste viděli základní teorii a praktické rysy E2E testování s Cypress. Použil jsem instalaci Joomla, abych demonstroval, jak psát různé testy, aby bylo zajištěno, že komponenta Joomla na webu funguje podle očekávání. Také jsem ukázal, jak přizpůsobit Cypress Test Runner v souboru cypress.json a jak používat přizpůsobené příkazy Cypress. To bylo provedeno pomocí snadno sledovatelných příkladů.
Doufám, že se vám prohlídka Cypress na příkladu Joomly líbila a že jste si mohli odnést spoustu znalostí a inspirace pro sebe.