Automatizace testování uživatelského rozhraní v systému iOS se stala stejně snadnou jako psaní jednotkových testů od doby, kdy Apple představil framework XCUI. V tomto příspěvku budu hovořit o tom, jak může XCUI ve spojení s vrstveným designem pomoci snadno automatizovat aplikace, zejména ty s více přizpůsobenými prvky uživatelského rozhraní. Jednou z takových aplikací, kde jsme toho hojně využili, je VMware Boxer, podniková aplikace od společnosti VMware, která sdružuje tři důležité funkce – e-mail, kalendář a kontakty. VMware Boxer používá více typů prvků uživatelského rozhraní od nativního UITableView až po vysoce přizpůsobené vizuální prvky.
Předpokládá se, že čtenáři mají základní znalosti Xcode, Objective C, Swiftu, frameworku XCUI a vývojového ekosystému Apple obecně. Pokud jste v oblasti XCUI nováčci, měli byste nejprve začít zde.
Stejně jako každý jiný projekt automatizace uživatelského rozhraní začal náš tým otázkou, jaký automatizační rámec použít. Dříve jsme používali SeeTest. Považovali jsme to však za příležitost přehodnotit naši strategii automatizace vzhledem k novým, komplexním funkcím přidaným ve VMware Boxer, počtu produktů v ekosystému VMware a integračním testům napříč těmito produkty. Níže jsou uvedeny možnosti, které jsme zvažovali –
1. Pokračovat se SeeTestem
2. Earl Grey
3. XCUI
Ačkoli SeeTest měl schopnost zvládnout naše okamžité potřeby automatizace, bylo třeba se vypořádat s nezávislým problémem. Vyžadovalo to, abychom přijali nový technologický stack. To by vyžadovalo další školení pro vývojáře iOS a specializované odborníky na údržbu automatizačního systému.
Co Appium? O Appium jsme neuvažovali ze stejných důvodů, které jsme uvedli výše u SeeTestu. Appium je dobrou volbou, pokud bychom měli hybridní aplikace nebo významný sdílený kód mezi Androidem a iOS.
Earl Grey 1 byl možnou volbou vzhledem k tomu, že nám umožňoval zůstat v Xcode a vývojových nástrojích Apple a byl založen na XCTestu. Automatizace Earl Grey 1 však běží ve stejném procesu jako testovaná aplikace. Naproti tomu automatizace založená na frameworku XCUI od společnosti Apple běží v samostatném procesu než testovaná aplikace. Tomu se dává přednost, protože testovaná aplikace by neměla být ničím jiným než černou skříňkou pro entitu (proces automatizace nebo koncového uživatele), která testuje její uživatelské rozhraní.
Mějte proces automatizace (ten, který testuje) izolovaný od vlastní testované aplikace. Testovaná aplikace by neměla být ničím jiným než černou skříňkou pro automatizující proces.
Každý nový nástroj v ekosystému Apple, který není v souladu s přístupem společnosti Apple (např. Earl Grey 1), může bez varování selhat. Takový přístup může vyžadovat velké úsilí na údržbu, aby nadále fungoval s novějšími nebo budoucími nabídkami společnosti Apple.
Early Grey 2 přidal možnost interakce s XCUI. Byl to pokus o sladění s XCUI, ale měl tyto známé problémy.
Nakonec bylo preferováno XCUI. Díky tomu bude mít vývojář větší kontrolu nad automatizací a bude bezprostředním příjemcem všech inovací v ekosystému Apple.
Testovaná aplikace a automatizační modul XCUI
Než se vrhneme na podrobnosti, je důležité zopakovat, že automatizační modul využívající XCUI běží jako proces nezávislý na testované aplikaci. Pro začátek jsme přidali nový modul, který budeme od nynějška označovat jako automatizační modul(AM). AM je pracovní prostor obsahující kolekci tříd a datových struktur používaných pro automatizaci VMware Boxer pomocí XCUI.
Identifikátory přístupnosti
Je důležité, aby aplikace byla vyvíjena s ohledem na její testovatelnost. Jednou z povinností vývojáře je zajistit, aby každý prvek uživatelského rozhraní, který je vystaven koncovému uživateli, měl při vývoji nastaven identifikátor přístupnosti. Identifikátor přístupnosti je spojovacím článkem mezi testovanou aplikací a procesem automatizace XCUI.
Identifikátor přístupnosti je spojovacím článkem mezi testovanou aplikací a procesem automatizace XCUI.
Jak již bylo zmíněno, VMware Boxer je obrovská aplikace. K výběru návrhového vzoru, který bude použit, se dospělo s ohledem na to, že testy by měly být snadno implementovatelné, snadno udržovatelné, opakovaně použitelné, robustní a škálovatelné. Následující obsah vysvětluje vrstvy architektury modulu XCUI Automation pro VMware Boxer:
Následující obrázek ukazuje základní stavební bloky:
Třídy testů
Jedná se o vrstvu, která obsahuje třídy obsahující testovací metody. Záměrem této vrstvy je, aby se testy skládaly z minimálního kódu, který říká pouze to, co se testuje. Také vývojář implementující testy musí myslet pouze na vysokoúrovňový tok aplikace potřebný k testování toho, co se testuje. Zbytek složitosti (např. jak přejít na uživatelské rozhraní, kde lze provést požadované testování) by měl být abstrahován do opakovaně použitelných vrstev. Viz obrázek níže, který ukazuje příklad testovací metody vysvětlující výše uvedený záměr – kód testuje, zda uživatelské rozhraní Nastavení může pomoci povolit/zakázat funkci nebo zda má požadované přepínací prvky.
Takže vývojář, který píše testy, by mohl napsat kód, který je stejně jednoduchý jako pseudokód. Přitom je jasné, že určitá logika by měla být vyvolána z další vrstvy (Flows : vysvětleno v následující části).
Třídy Flows
Třídy Flows představují kolekci tříd, které poskytují funkcionality potřebné pro různé třídy Testů. Funkcionality mohou zahrnovat nastavení aplikace před spuštěním skutečného testovacího případu nebo navigaci do určité části testované aplikace. Většina těchto funkcionalit je opakovaně použitelná a vyžadovaná ve více testech. např. výše uvedený ukázkový testovací případ vyžaduje, aby 1. byla spuštěna aplikace. a 2. byla spuštěna aplikace. Přejdeme na obrazovku nastavení řadiče funkcí.
Třídy Flow by tedy byly volány z testů a implementovaly by toky jako „Přejít na nastavení“ nebo „Přejít na nastavení řadiče funkcí“.
Třídy obrazovek
Třídy obrazovek jsou třídy, které mají mapování jedna ku jedné na příslušné řadiče zobrazení. View Controller lze na vysoké úrovni chápat jako třídu, která má (v záložním zobrazení) UIControls a metody, které reagují na interakci uživatele s těmito UIControls. Třída Screen je jednoduše proxy mapování View Controlleru. Toto mapování je znázorněno na obrázku níže. V uživatelském rozhraní je buňka Initial View a když uživatel klepne na tuto buňku, může si vybrat, co má být označeno jako počáteční zobrazení aplikace. Obrázek níže ukazuje, jak je implementována třída Screen, která mapuje výše uvedený požadavek.
Pseudokód této třídy Screen by vypadal takto –
// The class models the SettingFormViewController for XCUI tests.public class SettingsFormScreen {
private static let navBarId = "Boxer.Settings.NavigationBar"
private lazy var featureControllerCell = boxerApp.application.tables.cells public func navigateToFeatureController() -> Bool {
return // tap on Cell with featureControllerCellId
}
}class AccessibilityIdentifiers: NSObject {// MARK: Settings Screenstatic let featureControllerCellId = "Boxer.Settings.FeatureControllerCell"
}
co je to boxerApp ve výše uvedeném kódu? Ve výše uvedeném kódu boxerApp představuje jednotku, která je instancí třídy BoxerApp, která zapouzdřuje testovanou aplikaci a její obrazovky. To je vysvětleno v následující části.
Výše uvedený kód modeluje SettingFormViewController aplikace VMware Boxer. Konvence použitá při pojmenování třídy spočívá v tom, že název je odvozen od názvu řadiče zobrazení nahrazením přípony ViewController za Screen. Všimněte si také komfortní třídy, která má identifikátory přístupnosti.
Identifikátor přístupnosti je společným pojítkem mezi testovanou aplikací a automatizačním procesem XCUI.
Spojení: VMware Boxer XCUI Automation Module
Modul UITest testuje běžící aplikaci. Je důležité, aby model aplikace byl navržen tak, aby jedna instance testované aplikace byla jedinou jednotkou. To znamená, že testovaná aplikace by měla být vnímána jako kolekce tříd obrazovek účastnících se obchodních toků (kolekce tříd toků)které jsou vyvolávány z testů (kolekce tříd)na základě požadavku testu. Každá jednotka aplikace by měla mít přesně jednu instanci každé třídy Screen, která odpovídá jednomu kontroléru zobrazení.
Jak toho dosáhnout?
Sada testů XCUITest toho může dosáhnout zapouzdřením instance testované aplikace(XCUIApplication) do jedné jednotky, např. třídy BoxerApp, která má členskou aplikaci a má všechny obrazovky pro tuto aplikaci. Obrázek níže vysvětluje toto zapouzdření
Tuto instanci modulu BoxerApp (jednotka zapouzdřující XCUIApplication a Screens) pak předá Tests::testMethod modulu Flows::flowMethod jako první parametr.
Metoda Flows::flowMethod zase volá metodu Screen::screenMethod a v případě potřeby předává BoxerApp.
Konec interakce s uživatelským rozhraním aplikace probíhá prostřednictvím Screen::screenMethod.
Následující obrázek ukazuje výše uvedený návrh.
Závěr
Psaní testů XCUI může být těžkopádné a nezvládnutelné, pokud není prováděno s plánem. Doufám, že tento příspěvek poskytuje užitečné tipy, jak přemýšlet o strukturování projektu automatizace modulárním, čistým a vrstevnatým způsobem.
Co dál?
Těmito tématy se budu zabývat v sérii příběhů, kterou plánuji:
XCUI : Část 2 -Interakce s nativními aplikacemi čistým způsobem
XCUI : Část 3 -Jak může běhové prostředí XCUI interagovat s testovanou aplikací čistým způsobem.
XCUI : Část 4 -Obsluha systémových výstrah.
XCUI : Část 5 -Sledování průběhu testování a přístup k reportům a pořizování snímků obrazovky.
XCUI : Část 6 -Sledování průběhu testování a přístup k reportům a pořizování snímků obrazovky.