Automatyczne testy aplikacji mobilnych

9 czerwca 2017 11min.

Automatyczne testy aplikacji mobilnych

Testy są nieodłącznym elementem wytwarzania oprogramowania. Wykonuje się je przede wszystkim w celu znalezienia błędów, sprawdzania kompatybilności i stabilności aplikacji. Dopóki aplikacja jest mała, wszystkie testy jest w stanie wykonywać tester, ale z czasem konieczna jest automatyzacja – w której tematykę chciałbym dziś Was wprowadzić.

Zawartość artykułu:

  1. A na co to komu?
  2. Że co, że JA nie przetestuję?
  3. A jakie możliwości i zastosowania mają testy automatyczne?
  4. Czy testy automatyczne to faktycznie oszczędność?
  5. Krótka historia o testowaniu
  6. To jeszcze raz, gdzie ta oszczędność?
  7. Na czym polega pisanie testów automatycznych?
  8. Narzędzia
  9. Testy a Google
  10. Podsumowanie

A na co to komu?

Zacznę od trochę abstrakcyjnej historii. Wyobraźcie sobie, że pracujecie w fabryce i składacie samochody. Jest dokładnie jeden sposób, który gwarantuje, że samochód zostanie złożony poprawnie, a jego konstrukcja będzie spełniała wszystkie normy bezpieczeństwa i wytrzymałości. Teraz pomyślcie sobie, że cały proces obsługujecie sami… a teraz powtórzcie to sto razy. Nawet jeśli będzie to Wasza pasja i myślicie sobie: „Praca może i monotonna, ale przecież składam Lamborghini”, po pewnym czasie popadnięcie w rutynę, a to może generować niedopatrzenie, a często poważne błędy. I dokładnie to samo dzieje się z testami. Testy automatyczne oprócz ograniczenia kosztów w dłuższej perspektywie – ponieważ nie trzeba zatrudniać tylu testerów – pozwalają na wykonywanie wielokrotnie tych samych testów zawsze z tą samą dokładnością.

Że co, że JA nie przetestuję?

W przypadku programistów z reguły jest wręcz na odwrót (wiem po sobie). W X-Coding nasi programiści piszą testy jednostkowe w kodzie, aby zapewnić jak najwyższą jakość. Takie testy sprawdzają działanie aplikacji na najniższym poziomie (na poziomie metod), a uruchamiane automatycznie umożliwiają znalezienie błędów bardzo szybko. Niestety nie da się nimi sprawdzić wszystkiego, dlatego potrzebni są niezależni sędziowie, tacy jak testerzy oraz „bezduszne” automaty. Testerzy są niezastąpieni w przypadku testów UX, które oprócz mierzenia statystyk (np. ile kliknięć potrzeba, żeby zrealizować zamówienie) wymagają subiektywnej oceny działania aplikacji.

A jakie możliwości i zastosowania mają testy automatyczne?

Spore. Przede wszystkim praktycznie w całości można zautomatyzować:

  • Testy zaufania, które sprawdzają, czy aplikacja umożliwia np. realizację zamówienia w przypadku sklepu internetowego,
  • Stress testy – badające stabilność aplikacji,
  • Testy regresji – ssprawdzające, czy wprowadzenie nowej funkcjonalności nie wpłynęło na stare,
  • Testy kompatybilności – dzięki którym możemy szybko i dokładnie, sprawdzić jak aplikacja uruchamia się w zależności od wersji systemu, rozdzielczości czy geometrii ekranu. I najważniejsze — w celu spełnienia norm jakości, możemy sprawdzić ile czasu uruchamia się aplikacja, oraz jej poszczególne podstrony, w zależności od parametrów smartfona.

Czy testy automatyczne to faktycznie oszczędność?

W poprzednim artykule stwierdziłem, że jest to oczywiste, ale bez szerszego uzupełnienia to stwierdzenie jest lekkim nadużyciem. Zacznę więc od porównania testów automatycznych i manualnych. Do podstawowych przewag testów automatycznych nad manualnymi należą:

  • krótszy czas wykonania pojedynczego testu,
  • taka sama dokładność przy każdym wykonaniu,
  • możliwość działania 24/7,
  • możliwość niezależnego wykonywania testów i analizy wyników.

Natomiast wady testów automatycznych prezentują się następująco:

  • test automatyczny trzeba najpierw napisać, żeby się wykonał – co opóźnia rozpoczęcie testowania i znacznie zwiększa koszt przypadający na pierwszy test,
  • modernizacja aplikacji może pociągnąć za sobą również potrzebę zmiany testów automatycznych,
  • dłuższy czas potrzebny na analizę wyników testów – w przypadku testów manualnych analiza przebiega równolegle z testem,
  • sprawdzają one tylko i wyłącznie to, co mają zaprogramowane i nie ma szansy, że zobaczą coś „przy okazji”.

Lista pokazuje, że testy automatyczne nie są takie wspaniałe, jak je wcześniej opisywałem. Tak naprawdę napisanie ich jest droższe, czasochłonne, a potem jeszcze trzeba dokonać analizy wyników.

Dlaczego nadal twierdzę, że testy automatyczne prowadzą do oszczędności? Ponieważ w biznesie nie tworzy się aplikacji czy systemów „na zaliczenie” jak na studiach, tylko na lata. Nawet jeśli aplikacja się nie rozwija i jedyne prace są związane z jej utrzymaniem, to właśnie testy automatyczne pozwalają na szybkie wychwycenie błędów związanych np. z nieprzewidzianym formatem danych. Mimo że analiza wyników faktycznie jest dłuższa, to traci to na znaczeniu, ponieważ:

  • testów jest dużo więcej niż manualnych,
  • wyniki testów interpretuje się jako całość.

Krótka historia o testowaniu

Właściwa obsługa testów automatycznych od początku wymaga zespołu testerów. Do ich zadań, oprócz tworzenia i wykonywania testów należą również optymalizacja, utrzymanie testów i narzędzi testowych.

Czas na kolejną historię: wyobraźmy sobie dwie identyczne firmy, pracujące nad dokładnie tym samym projektem. Jedna z nich (nazwijmy ją M) korzysta wyłącznie z testerów manualnych, a druga (A) oprócz testów manualnych przeprowadza również testy automatyczne. Obie firmy rozpoczynają wdrożenie swojego produktu i jednocześnie testują nowe funkcjonalności. Firma M zaczyna z jednym testerem, przypadającym na 5 programistów, natomiast firma A od początku musi zatrudniać około 4 testerów, z tego jeden manualnie testuje nowe funkcjonalności, a reszta zajmuje się testami automatycznymi.

Wniosek nasuwa się sam – testy automatyczne będą droższe od testów manualnych. I mówimy tutaj wyłącznie o testerach na etacie. Statystyka potwierdza, że jest to prawdą przez pierwsze pół roku. I tu pojawia się „ale”, ponieważ wraz z rozbudową każdego systemu rośnie zapotrzebowanie na testerów. A im większy system, tym jeszcze więcej pomysłów na jego rozbudowę. Niestety praktyka pokazuje, że w wielu przypadkach nowa funkcjonalność wiąże się z mniejszą lub większą modyfikacją systemu.

Kiedyś słyszałem rozmowę dwóch programistów, podczas której jeden stwierdził, że naprawa błędów jest jak walka z Hydrą, usuniesz jedną głowę (błąd), a na jej miejscu wyrośnie 10 nowych. Testerzy manualni w większości przypadków nie są w stanie sprawdzić wszystkich miejsc, na które wpływ mogła mieć „drobna” modyfikacja. Nawet programiści, którzy tworzą system, nie muszą wiedzieć o wszystkich miejscach, na które ich drobna zmiana może mieć wpływ. Testy automatyczne nie narzekają i nie wybierają, tylko testują wszystko „jak leci”.

To jeszcze raz, gdzie ta oszczędność?

Chwilę wcześniej stwierdziłem, że wraz ze wzrostem rozmiarów systemu rośnie zapotrzebowanie na testerów i dotyczy to obu rodzajów testów. Różnica bierze się z tempa wzrostu tej liczby. Dokładnych wykresów niestety nikt nie jest w stanie przedstawić, ponieważ systemy szczególnie na początku dość mocno się zmieniają — zdarza się, że przebudowywana jest cała architektura systemu. Z tego powodu, pokrywanie wszystkiego od początku testami automatycznymi zamienia się w walkę z wiatrakami. Z kolei w przypadku testów manualnych kładzie się większy nacisk na przetestowanie dokładnie nowych funkcjonalności, pozostałe w zasadzie przeklikując.

Możemy za to porównać idealne przypadki. W takiej abstrakcyjnej sytuacji, testerzy manualni i automatyczni chcą wykonywać dokładnie tę samą pracę. Podczas gdy zapotrzebowanie na testerów manualnych rośnie liniowo, to tendencja wzrostu liczby testerów automatycznych będzie bliższa logarytmicznej. Poniższy wykres to tylko idea. W praktyce próbuje się znaleźć złoty środek pomiędzy pokryciem systemu testami automatycznymi a testami manualnymi.

Biorąc pod uwagę niektóre metodyki pracy programistycznej takie jak TDD (ang. Test Driven Development), część testów automatycznych, w tym przypadku uruchamianie testów jednostkowych, otrzymuje się w zasadzie za darmo. Pozostaje kwestia dostosowania narzędzia do uruchomienia testów.

Podsumowując moje „krótkie” uzupełnienie: zdrowe i przemyślane podejście do testów automatycznych skutkuje ograniczeniem kosztów w dłuższej perspektywie, zwiększeniem jakości kodu i krótszym czasem reakcji w przypadku pojawienia się błędów.

Na czym polega pisanie testów automatycznych?

Dla wielu osób spoza środowiska IT systemy informatyczne biorą się jakby „z powietrza”. Świetnie pokazuje to następujący schemat:

Powstawanie systemów IT
o naprawdę działa inaczej (źródło: https://thenextweb.com/wp-content/blogs.dir/1/files/2009/10/13449_full.jpg)

Tak samo jest w przypadku testów automatycznych. Za każdym testem stoi pewna historia (user story). Następnie przekłada się ona na listę kolejnych działań w aplikacji. Działania przekładają się z kolei na „kliknięcia przycisków”. Na podstawie tych kliknięć możemy tworzyć testy automatyczne. Czy to oznacza, że testować możemy tylko za pomocą kliknięć? Oczywiście, że nie. Wprawdzie niektóre narzędzia ograniczają się tylko do tego, ale testy mogą sprawdzać zachowanie aplikacji również w sytuacjach, na które użytkownik nie miał bezpośredniego wpływu. Przykładem takiego testu może być sprawdzenie, co się stanie, kiedy do użytkownika zadzwoni telefon podczas używania aplikacji.

Narzędzia

Na rynku jest wiele dostępnych narzędzi wspomagających pisanie i uruchamianie testów automatycznych. Należą do nich między innymi:

  • Appium – narzędzie open source, które pozwala na automatyzację aplikacji natywnych, webowych oraz hybrydowych,
  • UIAutomator – framework Googla, który pozwala na testowanie natywnych aplikacji (od API 18) oraz daje dostęp do procesów systemowych,
  • Robotium – również przeznaczony jest do testowania natywnych (Android) i hybrydowych aplikacji. Cytując oficjalny profil projektu na GitHubie: „Pozwala w prosty sposób na pisanie potężnych testów typu black-box”.

Część narzędzi do testów automatycznych to po prostu biblioteki do języków programowania. W przypadku Androida są to biblioteki Javowe. Pozostałe narzędzia umożliwiają nagrywanie zachowania — ruchu na ekranie — a następnie odtworzenie go w ramach testów. Wróćmy jednak do pierwszej grupy. Wyobraźmy sobie, że mamy aplikację z logowaniem i pewną testową parę loginu i hasła – te dane posłużą nam do sprawdzenia testu. Nasz widok składa się z dwóch pól EditText i przycisku zaloguj. Jak wygląda test logowania np. w Robotium?

public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> {

   private Solo solo;

   public LoginActivityTest() {
       super(LoginActivity.class);
   }

   public void setUp() throws Exception {
       solo = new Solo(getInstrumentation(), getActivity());
   }

   public void testLogIn() throws Exception {

       solo.enterText(0,"login");
       solo.enterText(1,"password");
       solo.clickOnButton("Zaloguj");

       Assert.assertTrue(solo.searchText("Logowanie pomyślne"));

   }

   @Override
   public void tearDown() throws Exception {
       solo.finishOpenedActivities();
   }

}

Analogicznie możemy — i nawet powinniśmy — napisać test, który sprawdzi, czy w przypadku błędnego hasła logowanie się nie powiodło. Dobre praktyki w testowaniu to jednak temat na oddzielny artykuł. Jest pełna dowolność w tworzeniu testów automatycznych. Można testować każdy ekran osobno, dzięki czemu bardzo szybko można „przemielić” ekran, na którym coś przestało działać. W przypadku testów manualnych należałoby przygotować osobne apk, żeby ograniczyć do minimum ilość kliknięć potrzebnych do sprawdzenia wszystkich kombinacji.

Testy a Google

Nie tak dawno na łamach naszego forum opisywaliśmy jak podłączyć się do Firebase. Zachęcam do zapoznania się jeszcze raz z artykułem. Przybliżę teraz inne narzędzie z tej konsoli, a mianowicie Test Lab.

Firebase umożliwia uruchamianie własnych testów, napisanych z użyciem którejś z bibliotek. Aby to zrobić, musimy wpierw spakować apk z aplikacją oraz osobne apk z testami. Następnie należy umieścić oba pliki na serwerze, wybrać docelowe urządzenia do przetestowania, a po zakończeniu wykonania testów otrzymamy wyniki. W przypadku aplikacji natywnych możemy również uruchomić test Robo. Taki test uruchamia naszą aplikację w formie drzewa i sprawdza wszystkie ścieżki, do których może dotrzeć.

W darmowym planie można wykonać 10 testów dziennie. Nie jest to dużo, ale na indywidualne potrzeby i szybkie reagowanie powinno wystarczyć. Nawet taka mała ilość przydaje się, gdy otrzymamy powiadomienie (też z Firebase), o błędzie u któregoś z użytkowników. Sam Firebase oprócz przechwytywania zdefiniowanych błędów i komunikatów, zbiera również informacje o nieprzewidzianych błędach. Korzystając z zapisanej zawartości stosu, jesteśmy w stanie znaleźć wadliwy ekran i uruchomić testy dla tego ekranu – i to wszystko bez zaawansowanej infrastruktury szybkiego reagowania.

Podsumowanie


Testy automatyczne mogą budzić kontrowersje, w szczególności ze względu na wyższy koszt wdrożenia. Niemniej jednak, stosując je mądrze, można zyskać, dzięki zwiększeniu jakości kodu i stosunku pokrycia go testami.