Używanie podwójnej precyzji testów na Androidzie

Podczas projektowania strategii testowania elementu lub systemu należy wziąć pod uwagę powiązane aspekty testowania:

  • Zakres: jaka część kodu obejmuje test? Testy mogą zweryfikować całą aplikację lub gdzieś pomiędzy. zakres testowany jest w trakcie testowania i jest często określany jako Subject Under Testuj, a także System w trakcie testowania lub Jednostka w trakcie testowania.
  • Szybkość: jak szybko przebiega test? Szybkość testu może się różnić w zależności od milisekund do kilku minut.
  • Fidelity (jak autentyczne). Czy to test? Jeśli na przykład część kodu który testujesz, musi wysłać żądanie sieciowe, czy kod testowy faktycznie to żądanie sieciowe, czy też wynik jest fałszywy? Jeśli test faktycznie mówi z siecią, ma wyższą jakość obrazu. Z drugiej strony test może potrwać dłużej, może spowodować błędy w przypadku awarii sieci lub może być kosztowny.

Zobacz, co testować, by dowiedzieć się, jak rozpocząć definiowanie strategii testowej.

Izolacja i zależności

Gdy testujesz element lub system pierwiastków, robisz to w izolacji. Dla: Przykład: aby przetestować model ViewModel, nie trzeba uruchamiać emulatora ani interfejsu użytkownika bo nie zależy to (lub nie) od platformy Androida.

Skuteczność testu może jednak zależyć od innych. Dla: model ViewModel może zależeć od repozytorium danych.

Gdy trzeba podać zależność od testowanego obiektu, często stosowana metoda to utworzenie podwójnej precyzji testowej (lub obiektu testowego). Podwójne wartości testowe to obiekty, które wyglądają i działają jak komponenty aplikacji, ale są tworzone w teście, w których użytkownicy zachęcają widzów do działania lub udostępniają dane. Największą zaletą jest to, że pozwalają testowanie trwa szybciej i łatwiej.

Rodzaje podwójnej precyzji testowej

Występują różne rodzaje podwójnej precyzji testowej:

Nieprawdziwe dane Podwójny plik testowy, który ma „działający” element i została zaimplementowany w sposób, który sprawia, że sprawdza się on dobrze w testach, ale nie nadaje się do produkcji.

Przykład: baza danych działająca w pamięci.

Fałszywe materiały nie wymagają żartu i są lekkie. Są one preferowane.

Przykład Podwójny test, który zachowuje zgodność z określonym przez Ciebie działaniem i określa oczekiwania dotyczące interakcji. Próby nie zakończą testów, jeśli ich interakcje nie będą zgodne ze zdefiniowanymi przez Ciebie wymaganiami. Aby osiągnąć ten cel, w przykładach używa się zwykle platformy do tworzenia próbek.

Przykład: sprawdź, czy metoda w bazie danych została wywołana dokładnie raz.

Odcinek Podwójny test, który zachowuje się w określony sposób, w jaki zaprogramujesz działanie, ale nie ma oczekiwań co do interakcji. Zwykle tworzone z użyciem platformy służącej do krzywdzenia. Dla uproszczenia mają pierwszeństwo przed wycinkami filmów.
pusty Podwójny parametr testowy, który jest przekazywany, ale nie jest używany, np. trzeba go tylko podać jako parametr.

Przykład: pusta funkcja przekazana jako wywołanie zwrotne kliknięcia.

Szpiegowski Otoczenie nad prawdziwym obiektem, które również rejestruje dodatkowe informacje, przypominające przykłady. Zwykle unikaj ich, aby zwiększyć złożoność. Dlatego fałszerstwa lub żarty są preferowane przed szpiegami.
Cień Fałszywy materiał stosowany w Robolectric.

Przykład z użyciem fałszywego

Załóżmy, że chcesz przetestować jednostkowy model ViewModel zależny od interfejsu UserRepository i ujawnia w interfejsie nazwę pierwszego użytkownika. Dostępne opcje utworzyć podwójny test, implementując interfejs i zwracając i skalowalnych danych.

object FakeUserRepository : UserRepository {
    fun getUsers() = listOf(UserAlice, UserBob)
}

val const UserAlice = User("Alice")
val const UserBob = User("Bob")

Ten fałszywy UserRepository nie musi polegać na danych lokalnych ani zdalnych źródeł, których będzie używać wersja produkcyjna. Plik znajduje się w źródle testowym i nie będą wysyłane razem z wersją produkcyjną aplikacji.

Fałszywa zależność może zwracać znane dane bez korzystania ze zdalnych źródeł danych
Rysunek 1. Fałszywa zależność w teście jednostkowym.

Ten test sprawdza, czy model ViewModel prawidłowo udostępnia pierwszego użytkownika nazwę widoku.

@Test
fun viewModelA_loadsUsers_showsFirstUser() {
    // Given a VM using fake data
    val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init

    // Verify that the exposed data is correct
    assertEquals(viewModel.firstUserName, UserAlice.name)
}

Zastępowanie elementu UserRepository fałszywą treścią jest łatwe w teście jednostkowym, ponieważ Model ViewModel jest tworzony przez testera. Zastąpić ją tym może być jednak dowolnych elementów w większych testach.

Zastępowanie komponentów i wstrzykiwanie zależności

Jeśli testy nie mają kontroli nad tworzeniem testowanych systemów, zamienianie komponentów dla podwójnej precyzji w testach staje się bardziej pracochłonne i wymaga architekturę aplikacji, aby była zgodna z testowalną konstrukcją.

Nawet duże, kompleksowe testy mogą skorzystać na podwójnej precyzji, np. z instrumentalizowanym testem interfejsu, który analizuje cały przepływ użytkownika w aplikacji. W w takim przypadku warto ustawić test hermetyczny. Test hermetyczny pozwala uniknąć wszystkich zależności zewnętrznych, takich jak pobieranie danych z internetu. Ten poprawia niezawodność i wydajność.

Rysunek 2. Duży test obejmujący większość aplikacji i fałszywe dane zdalne.

Możesz zaprojektować aplikację w taki sposób, aby osiągnąć tę elastyczność ręcznie, ale zalecamy za pomocą platformy wstrzykiwania zależności, np. Hilt, aby zastąpić komponenty. w aplikacji w momencie testowania. Zobacz przewodnik testowania Hilt.

Robolectric

W przypadku Androida można korzystać z platformy Robolectric, udostępnia specjalny typ podwójnej precyzji. Robolectric umożliwia przeprowadzanie testów w Twojej stacji roboczej czy w środowisku ciągłej integracji. Wykorzystuje Zwykła JVM, bez emulatora ani urządzenia. Symuluje wzrost liczby wyświetleń, wczytywanie zasobów i inne elementy platformy Androida z testowaniem podwójnej precyzji tzw. cienie.

Robolectric to symulator, dlatego nie powinien zastępować prostych testów jednostkowych ani być używany aby przetestować zgodność. Zapewnia szybkość i obniża koszty w niektórych przypadkach niższa wierność. W przypadku testów interfejsu warto zadbać o to, jest kompatybilna zarówno z testami Robolectric, jak i instrumentowanymi oraz określa, kiedy przeprowadzać testy. w zależności od potrzeby przetestowania ich funkcjonalności lub zgodności. Espresso a testy Compose mogą być uruchamiane w Robolectric.