Podstawy testowania aplikacji na Androida

Na tej stronie znajdziesz podstawowe zasady testowania aplikacji na Androida, w tym najważniejsze sprawdzone metody i ich zalety.

Korzyści z testowania

Testowanie jest nieodłączną częścią procesu tworzenia aplikacji. Regularne przeprowadzanie testów aplikacji umożliwia weryfikowanie poprawności jej działania, funkcjonalności i łatwości obsługi jeszcze przed opublikowaniem.

Możesz przetestować aplikację ręcznie, przechodząc przez nią. Możesz użyć różnych urządzeń i emulatorów, zmienić język systemu i spróbować generować błędy każdego użytkownika.

Ręczne testowanie nie skaluje się jednak dobrze, a regressję w zachowaniu aplikacji można łatwo przeoczyć. Testowanie automatyczne polega na korzystaniu z narzędzi, które wykonują testy za Ciebie. Jest to szybsze i bardziej powtarzalne rozwiązanie, które pozwala uzyskać przydatne opinie na temat aplikacji na wczesnym etapie procesu tworzenia.

Rodzaje testów w Androidzie

Aplikacje mobilne są złożone i muszą dobrze działać w wielu środowiskach. Z tego powodu jest wiele rodzajów testów.

Temat

W zależności od przedmiotu dostępne są różne typy testów:

  • Testowanie funkcjonalności: czy moja aplikacja działa zgodnie z oczekiwaniami?
  • Testy wydajności: czy aplikacja działa szybko i wydajnie?
  • Testowanie ułatwień dostępu: czy dobrze współpracuje z usługami ułatwień dostępu?
  • Testy zgodności: czy aplikacja działa prawidłowo na każdym urządzeniu i przy każdym poziomie interfejsu API?

Zakres

Testy różnią się też w zależności od rozmiaru lub stopnia izolacji:

  • Testy jednostkowe lub małe testy sprawdzają tylko bardzo małą część aplikacji, na przykład metodę lub klasę.
  • Testy kompleksowe lub testy obszerne sprawdzają większe części aplikacji w tym samym czasie, np. cały ekran lub ścieżkę użytkownika.
  • Pomiędzy co najmniej 2 jednostkami znajdują się testy średnich i sprawdzają integrację.
Testy mogą być małe, średnie lub duże.
Rysunek 1. Zakresy testów w typowej aplikacji.

Testy można klasyfikować na wiele sposobów. Najważniejsza różnica dla deweloperów aplikacji to miejsce, w którym są wykonywane testy.

Testy z użyciem instrumentacji a testy lokalne

Testy możesz przeprowadzać na urządzeniu z Androidem lub na innym komputerze:

  • Testy z użyciem instrumentacji są wykonywane na urządzeniu z Androidem, zarówno na urządzeniu fizycznym, jak i na emulowanym. Aplikacja jest skompilowana i instalowana wraz z aplikacją testową, która wstrzykiwa polecenia i odczytuje stan. Testy z użyciem instrumentacji to zwykle testy interfejsu użytkownika, które polegają na uruchomieniu aplikacji i następnie na interakcji z nią.
  • Testy lokalne są wykonywane na komputerze programistycznym lub serwerze, dlatego nazywa się je też testami po stronie hosta. Zazwyczaj są małe i szybkie, odizolując testowany obiekt od reszty aplikacji.
Testy mogą być wykonywane jako testy z instrumentacją na urządzeniu lub testy lokalne na komputerze programisty.
Ilustracja 2. Różne typy testów w zależności od miejsca ich wykonywania.

Nie wszystkie testy jednostkowe są testami lokalnymi, a nie wszystkie testy kompleksowe są wykonywane na urządzeniu. Przykład:

  • Duży test lokalny: możesz użyć symulatora Androida, który działa lokalnie, np. Robolectric.
  • Mały test z użyciem instrumentacji: możesz sprawdzić, czy Twój kod działa prawidłowo z funkcją frameworka, np. z bazą danych SQLite. Aby sprawdzić integrację z wieloma wersjami SQLite, możesz uruchomić ten test na wielu urządzeniach.

Przykłady

Poniższe fragmenty kodu pokazują, jak wchodzić w interakcję z interfejsem w testie UI z użyciem instrumentacji, który klika element i sprawdza, czy wyświetla się inny element.

Espresso

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

Interfejs tworzenia wiadomości

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

Ten fragment kodu pokazuje część testu jednostkowego dla ViewModel (test lokalny po stronie hosta):

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

Testowalna architektura

W przypadku architektury aplikacji umożliwiającej testowanie kod ma strukturę, która pozwala łatwo testować poszczególne jej części. Testowalne architektury mają też inne zalety, takie jak lepsza czytelność, łatwość konserwacji, skalowalność i możliwość ponownego użycia.

Architektura, której nie można przetestować, zapewnia:

  • Większe, wolniejsze i bardziej niestabilne testy. Klasy, których nie można testować jednostkowo, mogą wymagać przeprowadzenia bardziej rozbudowanych testów integracji lub testów interfejsu użytkownika.
  • Mniej możliwości testowania różnych scenariuszy. Większe testy są wolniejsze, więc testowanie wszystkich możliwych stanów aplikacji może być nierealne.

Więcej informacji o wytycznych dotyczących architektury znajdziesz w przewodniku po architekturze aplikacji.

Metody rozdzielenia

Jeśli możesz wyodrębnić część funkcji, klasy lub modułu z reszty, testowanie jest łatwiejsze i skuteczniejsze. Ta praktyka nazywa się rozdzielaniem i jest koncepcją najważniejszą dla architektury testowalnej.

Popularne techniki usuwania połączeń to między innymi:

  • Dzielenie aplikacji na warstwy, takie jak prezentacja, domena i dane. Aplikację możesz też podzielić na moduły, po jednym na każdą funkcję.
  • Unikaj dodawania logiki do elementów, które mają wiele zależności, takich jak aktywności i fragmenty. Używaj tych klas jako punktów wejścia do frameworka i przenoś interfejs użytkownika i logikę biznesową w inne miejsce, np. do warstwy Composable, ViewModel lub domeny.
  • W klasach zawierających logikę biznesową unikaj bezpośrednich zależności od struktury. Na przykład nie używaj kontekstów Androida w klasach ViewModel.
  • Ułatwić zastępowanie zależności. Zamiast konkretnych implementacji użyj na przykład interfejsów. Używaj wstrzykiwania zależności, nawet jeśli nie używasz frameworku DI.

Dalsze kroki

Teraz, gdy już wiesz, dlaczego warto przeprowadzać testy i jakie są 2 główne ich rodzaje, możesz przeczytać artykuł Co testować lub dowiedzieć się więcej o strategiach testowania.

Jeśli chcesz utworzyć pierwszy test i uczyć się w praktyce, skorzystaj z laboratoriów kodowania testów.