Wprowadzenie do testowania iOS z UI Automation

kw. 17, 2021
admin

Wyobraź sobie możliwość pisania skryptów, które automatycznie wchodzą w interakcję z Twoją aplikacją iOS i są w stanie zweryfikować wyniki. Dzięki UI Automation możesz to zrobić. UI Automation jest narzędziem dostarczonym przez Apple do wykonywania wyższego poziomu testowania aplikacji iOS, niż wszystko co można osiągnąć za pomocą XCTest.

1. Testowanie białej skrzynki kontra testowanie czarnej skrzynki

Może słyszałeś porównanie testowania białej skrzynki z testowaniem czarnej skrzynki w odniesieniu do tego jak można testować kawałek oprogramowania. Jeśli nie jesteś zaznajomiony z tymi pojęciami, pozwól mi wyjaśnić jak one działają.

Testowanie białej skrzynki

Wyobraź sobie, że kawałek oprogramowania działa wewnątrz skrzynki. Dzięki testom białej skrzynki, możesz zajrzeć do środka i przyjrzeć się wszystkim drobnym elementom tego, jak działa oprogramowanie, a następnie podjąć świadomą decyzję, jak przetestować oprogramowanie. Możesz również mieć głębszy poziom haków do oprogramowania z testów, które piszesz.

Testy jednostkowe są testami białej skrzynki. Podczas pisania testów jednostkowych, tester ma drobnoziarnisty dostęp do testowanego kodu. Tester może w rzeczywistości pisać testy, które wykorzystują testowane oprogramowanie na poziomie metody lub jednostki.

W rozwoju oprogramowania iOS używamy frameworka XCTest do wykonywania tego typu testów. Spójrz na inny tutorial, który napisałem na temat rozpoczęcia pracy z XCTest.

Testy czarnej skrzynki

W testach czarnej skrzynki, skrzynka jest nieprzezroczysta. Tester nie może zobaczyć wnętrza pudełka. Tester nie ma dostępu i nie wie o implementacji bazy kodu do pisania testów. Zamiast tego, tester jest zmuszony do korzystania z aplikacji tak, jak zrobiłby to użytkownik końcowy, wchodząc w interakcję z aplikacją i czekając na jej odpowiedź, weryfikując wyniki.

Istnieją co najmniej dwa sposoby wykonania tego typu testów.

  • Tester, który wielokrotnie i ręcznie wykonuje pewną liczbę predefiniowanych kroków i wizualnie weryfikuje wyniki.
  • Użycie wyspecjalizowanych narzędzi do testowania aplikacji z interfejsami API, które zachowują się podobnie do sposobu interakcji człowieka.

W rozwoju aplikacji iOS, Apple dostarcza narzędzie o nazwie UI Automation do przeprowadzania testów czarnej skrzynki.

2. Czym jest UI Automation?

UI Automation jest narzędziem, które Apple dostarcza i utrzymuje dla wyższego poziomu, zautomatyzowanego testowania aplikacji iOS. Testy są pisane w JavaScript, zgodnie z API zdefiniowanym przez Apple.

Pisanie testów może być łatwiejsze poprzez poleganie na etykietach dostępności dla elementów interfejsu użytkownika w twojej aplikacji. Nie martw się jednak, jeśli nie masz ich zdefiniowanych, są dostępne alternatywy.

W UI Automation API brakuje typowego formatu pisania testów opartego na xUnit. Jedną różnicą z testami jednostkowymi jest to, że tester musi ręcznie rejestrować sukcesy i porażki. Testy UI Automation są uruchamiane z instrumentu Automation w narzędziu Instruments, które jest dostarczane z narzędziami deweloperskimi Apple. Testy mogą być uruchamiane w symulatorze iOS lub na fizycznym urządzeniu.

3. Pisanie testów UI Automation

Krok 1: Otwórz przykładowy projekt

Zaktualizowałem przykładowy projekt używany w poprzednim tutorialu na temat testowania iOS z kilkoma dodatkowymi elementami interfejsu użytkownika, które zapewniają kilka użytecznych haków do dodawania testów UI Automation. Pobierz projekt z GitHuba. Otwórz projekt i uruchom aplikację, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami. Powinieneś zobaczyć interfejs użytkownika podobny do tego pokazanego poniżej.

Zanim napiszemy jakiekolwiek testy, nie krępuj się wypróbować przykładowej aplikacji, aby zapoznać się z jej funkcjonalnością. Jako użytkownik, możesz wprowadzić tekst w polu tekstowym i dotknąć przycisku, aby zobaczyć etykietę na ekranie, która wyświetla odwrócony, wprowadzony ciąg znaków.

Krok 2: Tworzenie testu UI Automation

Teraz, gdy jesteś zaznajomiony z przykładową aplikacją, nadszedł czas, aby dodać test UI Automation. UI Automation jest narzędziem, które można znaleźć w Instruments. Aby uruchomić przykładową aplikację w Instruments, wybierz Product > Profile z menu Xcode. Z listy narzędzi wybierz Automation.

Otworzy się główne okno Instruments z jednym narzędziem gotowym do uruchomienia, instrumentem Automation (instrument Automation wykonuje przypadki testowe UI Automation). Zobaczysz także obszar w dolnej połowie okna, który wygląda jak edytor tekstu. To jest edytor skryptów. To tutaj będziesz pisał swoje testy UI Automation. Dla tego pierwszego testu, wykonaj poniższe instrukcje, dodając każdą linię do skryptu w edytorze skryptów.

Zacznij od zapisania odniesienia do pola tekstowego w zmiennej.

var inputField = target.frontMostApp().mainWindow().textFields();

Ustaw wartość pola tekstowego.

inputField.setValue("hi");

Weryfikuj, czy wartość została ustawiona pomyślnie i, jeśli tak, zalicz test. Fail the test if it wasn’t.

While this test is fairly trivial, it does have value. Właśnie napisaliśmy test, który sprawdza obecność pola tekstowego podczas uruchamiania aplikacji i który sprawdza, czy losowy ciąg znaków może być ustawiony jako wartość pola tekstowego. Jeśli mi nie wierzysz, to usuń pole tekstowe z storyboardu i uruchom test. Zobaczysz, że test się nie powiedzie.

Test ten demonstruje trzy ważne elementy pisania testów UI Automation. Po pierwsze, pokazuje on jak uzyskać dostęp do prostego elementu interfejsu użytkownika, pola tekstowego. Konkretnie, uzyskujemy dostęp do słownika wszystkich pól tekstowych w widoku bazowym aplikacji poprzez target.frontMostApp().mainWindow().textFields(), a następnie znajdujemy interesujące nas pole tekstowe, szukając tego z kluczem Input Field. Klucz ten jest w rzeczywistości etykietą dostępności pola tekstowego. W tym przypadku jest ona zdefiniowana w storyboardzie. Możemy również ustawić etykietę dostępności w kodzie, używając właściwości accessibilityLabel na NSObject.

Uzyskiwanie dostępu do głównego okna aplikacji, najbardziej frontowej aplikacji i celu jest powszechne podczas pracy z UI Automation. Pokażę ci, jak to zrobić łatwiej i mniej czasochłonnie w dalszej części tego poradnika.

Po drugie, to pokazuje, że możesz wchodzić w interakcję z elementami interfejsu użytkownika na ekranie. W tym przypadku, ustawiamy wartość pola tekstowego, naśladując użytkownika wchodzącego w interakcję z aplikacją poprzez wprowadzenie tekstu do pola tekstowego.

Po trzecie, przykład pokazuje również technikę sprawdzania tego, co dzieje się w aplikacji. Jeśli wartość zostanie pomyślnie ustawiona, test przechodzi. Jeśli wartość nie jest ustawiona, test kończy się niepowodzeniem.

Krok 3: Zapisywanie testów

Choć pisanie testów w edytorze skryptów jest wygodne, szybko staje się uciążliwe i trudne do utrzymania. Jeśli opuścisz Instruments, wszelkie niezapisane zmiany są odrzucane. Musimy zapisywać napisane przez nas testy. Po prostu skopiuj i wklej swój test do nowego dokumentu w ulubionym edytorze tekstu i zapisz go. Testy utworzone w tym poradniku można znaleźć w przykładowym projekcie w Jumblify/JumblifyTests/AutomationTests.js.

Aby uruchomić test, wybierz środkową zakładkę w panelu po prawej stronie, obok edytora skryptów, i wybierz Add > Import.

Zostaniesz poproszony o wybranie skryptu do zaimportowania. Przejdź do zapisanego skryptu i zaimportuj go. Skrypt można nadal zmieniać w edytorze skryptów. Wszelkie zmiany zostaną automatycznie zapisane w zewnętrznym pliku, który utworzyłeś.

Krok 4: Tapping a Button

Zaktualizujmy nasz test, aby przetestować interakcję z przyciskiem. Nasz test już dodaje tekst do pola tekstowego, więc musimy tylko dodać kod, aby dotknąć przycisku. Zastanówmy się najpierw jak znaleźć przycisk w widoku tak, aby można było go dotknąć. Istnieją co najmniej trzy sposoby, aby to osiągnąć i każdy z nich ma swoje zalety.

Podejście 1

Możemy programowo stuknąć współrzędną (X, Y) na ekranie. Robimy to za pomocą następującej linii kodu:

target.tap({x: 8.00, y: 50.00});

Oczywiście, nie mam pojęcia, czy to są w ogóle współrzędne przycisku na ekranie i nie zamierzam się tym przejmować, ponieważ to podejście nie jest właściwym narzędziem do tego zadania. Wspominam o nim tylko po to, żebyś wiedział, że istnieje. Użycie metody tap na target do dotknięcia przycisku jest podatne na błędy, ponieważ ten przycisk nie zawsze może znajdować się na tej konkretnej współrzędnej.

Podejście 2

Możliwe jest również znalezienie przycisku poprzez przeszukanie tablicy przycisków okna głównego, podobnie jak w przypadku dostępu do pola tekstowego w pierwszym teście. Zamiast bezpośredniego dostępu do przycisku za pomocą klucza, możemy pobrać tablicę przycisków głównego okna i zakodować na sztywno indeks tablicy, aby uzyskać odniesienie do przycisku.

target.frontMostApp().mainWindow().buttons().tap();

Takie podejście jest nieco lepsze. Nie kodujemy współrzędnej, ale twardo kodujemy indeks tablicy, aby znaleźć przycisk. Jeśli zdarzy nam się dodać inny przycisk na stronie, może to przypadkowo złamać ten test.

Podejście 3

To prowadzi mnie do trzeciego sposobu na znalezienie przycisku na stronie, używając etykiet dostępności. Używając etykiety dostępności, możemy uzyskać bezpośredni dostęp do przycisku, tak jak byśmy znaleźli obiekt w słowniku używając klucza.

target.frontMostApp().mainWindow().buttons().tap();

Jednakże, jeśli dodasz powyższą linię do skryptu i uruchomisz go, otrzymasz błąd.

Powodem tego jest fakt, że nie zdefiniowaliśmy jeszcze etykiety dostępności dla przycisku. Aby to zrobić, przejdź do Xcode i otwórz storyboard projektu. Znajdź przycisk w widoku i otwórz Inspektor Tożsamości po prawej stronie (Widok > Narzędzia > Inspektor Tożsamości). Upewnij się, że Dostępność jest włączona i ustaw Etykieta dla przycisku na Jumblify Button.

Aby ponownie uruchomić test, będziesz musiał uruchomić aplikację z Xcode, wybierając Produkt > Uruchom, a następnie ponownie profilować aplikację, wybierając Produkt > Profil. To uruchamia testy i każdy z nich powinien teraz przejść.

Krok 5: Zweryfikuj pomieszany ciąg

Jak wspomniałem wcześniej, nasza aplikacja przyjmuje ciąg tekstu jako dane wejściowe, a gdy użytkownik dotknie przycisku, wyświetla odwrócony ciąg. Musimy dodać jeszcze jeden test, aby sprawdzić, czy łańcuch wejściowy jest poprawnie odwrócony. Aby sprawdzić, czy UILabel jest wypełniony poprawnym łańcuchem, musimy wymyślić, jak odwołać się do UILabel i zweryfikować łańcuch, który wyświetla. Jest to częsty problem podczas pisania testów automatyzacji, czyli wymyślanie, jak odwołać się do elementu w aplikacji, aby wykonać na nim asercję.

Na prawie każdym obiekcie w UI Automation API znajduje się metoda logElementTree. Ta metoda rejestruje elementy zagnieżdżone danego elementu. Jest to bardzo przydatne do zrozumienia hierarchii elementów w aplikacji i pomaga zorientować się, jak celować w konkretny element.

Zobaczmy, jak to działa, logując drzewo elementów okna głównego. Spójrzmy na poniższy wiersz kodu.

target.frontMostApp().mainWindow().logElementTree();

Dodanie tego wiersza do skryptu testowego daje następujący wynik:

Jak widać, istnieje podelement UIAStaticText w elemencie UIAWindow i można również zauważyć, że ma on nazwę ih, która jest również odwróconym ciągiem znaków, który musimy zweryfikować. Teraz, aby zakończyć nasz test, musimy tylko dodać kod, aby uzyskać dostęp do tego elementu i sprawdzić, czy jest on obecny.

Dlaczego musimy tylko sprawdzić, czy element UIAStaticText jest obecny? Ponieważ nazwa tego elementu jest odwróconym łańcuchem wejściowym, sprawdzenie jego obecności potwierdza, że łańcuch został poprawnie odwrócony. Jeśli element nie istnieje, gdy odwołuje się do nazwy – odwróconego łańcucha – oznacza to, że łańcuch nie został poprawnie odwrócony.

4. Zdrapywanie powierzchni

Istnieje tak wiele innych sposobów, że użytkownik końcowy może wchodzić w interakcję z urządzeniem iOS podczas korzystania z aplikacji. Oznacza to, że istnieje wiele innych sposobów, które można wykorzystać UI Automation do symulacji tych interakcji. Zamiast próbować uchwycić wyczerpującą listę tych interakcji, skieruję Cię do dokumentacji referencyjnej UI Automation.

Dla każdego typu obiektu, z którym możesz wejść w interakcję, możesz wyświetlić listę metod dostępnych na tym obiekcie. Niektóre metody służą do pobierania atrybutów o obiekcie, podczas gdy inne służą do symulowania interakcji dotykowej, takiej jak flickInsideWithOptions na UIAWindow.

Recording a Session

Jak będziesz próbował testować coraz bardziej skomplikowane aplikacje za pomocą UI Automation, przekonasz się, że czasami dość żmudne jest wielokrotne używanie logElementTree, aby znaleźć element, którego szukasz. Staje się to również uciążliwe i skomplikowane dla aplikacji ze złożoną hierarchią widoków lub nawigacją. W takich przypadkach można użyć innej funkcji Instruments, aby nagrać zestaw interakcji użytkownika. Co jest jeszcze fajniejsze, Instruments generuje kod JavaScript automatyzacji UI, który jest potrzebny do odtworzenia nagranych interakcji. Oto jak możesz to wypróbować dla siebie.

W Instruments i z wybranym instrumentem Automation, poszukaj przycisku nagrywania na dole okna.

Jeśli klikniesz przycisk nagrywania, Instruments rozpocznie sesję nagrywania jak pokazano na poniższym zrzucie ekranu.

Instruments uruchomi twoją aplikację w symulatorze iOS i będziesz mógł wejść z nią w interakcję. Instruments wygeneruje skrypt na podstawie twoich interakcji w czasie rzeczywistym. Spróbuj. Obracaj symulator iOS, stukaj w losowych miejscach, wykonuj gesty machnięcia itp. To naprawdę przydatny sposób, który pomoże zbadać możliwości automatyzacji UI.

Avoiding a Monolithic Code Base

Jak zapewne możesz przewidzieć, jeśli nadal będziemy dodawać kolejne testy do pliku testowego, który stworzyliśmy w tej samej metodzie, szybko stanie się on trudny do utrzymania. Co możemy zrobić, aby temu zapobiec. W moich testach robię dwie rzeczy, aby rozwiązać ten problem:

  • Jeden test dla jednej funkcji: Sugeruje to, że testy, które piszemy, muszą być skoncentrowane na konkretnym fragmencie funkcjonalności. Nadam mu nawet odpowiednią nazwę, np. testEmptyInputField.
  • Grupowanie powiązanych testów w jednym pliku: Ja również grupuję powiązane testy w tym samym pliku. Dzięki temu kod w jednym pliku jest łatwy do zarządzania. Ułatwia to również testowanie oddzielnych części funkcjonalności poprzez wykonywanie testów w konkretnym pliku. Dodatkowo, możesz stworzyć skrypt główny, w którym wywołasz funkcje lub testy, które zgrupowałeś w innych plikach testowych.

W poniższym snippecie kodu, importujemy plik JavaScript i to sprawia, że funkcje w tym pliku JavaScript są dla nas dostępne.

#import "OtherTests.js"

Podsumowanie

W tym tutorialu, poznałeś wartość testów wyższego poziomu i jak UI Automation może pomóc wypełnić tę lukę. Jest to kolejne narzędzie w twoim zestawie narzędzi, które pomoże ci zapewnić, że dostarczasz niezawodne i solidne aplikacje.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.