Test lokalny odbywa się bezpośrednio na Twojej stacji roboczej, a nie na Androidzie urządzenia lub emulatora. Do testowania używa lokalnej maszyny wirtualnej Java (JVM), a nie urządzenia z Androidem. Testy lokalne umożliwiają szybsze sprawdzanie logiki aplikacji. Jednak brak możliwości interakcji Platforma Androida ogranicza liczbę dostępnych testów.
Test jednostek sprawdza zachowanie niewielkiej części kodu, jednostki test. Dzieje się to przez wykonanie tego kodu i sprawdzenie wyniku.
Testy jednostkowe są zwykle proste, ale ich konfiguracja może stanowić problem, jeśli jednostka w trakcie testowania nie jest zaprojektowany z myślą o możliwości testowania:
- Kod, który chcesz zweryfikować, musi być dostępny w ramach testu. Na przykład nie możesz bezpośrednio testować metody prywatnej. Zamiast tego testujesz klasę za pomocą publicznych interfejsów API.
- Aby można było przeprowadzić testy jednostkowe w izolacji, zależności jednostki w trakcie testów muszą zostać zastąpione komponentami, które kontrolujesz, takimi jak podróbki lub inne podwojenie testowe. Jest to szczególnie problematyczne, jeśli Twój kod zależy od platformy Android.
Aby dowiedzieć się więcej o popularnych strategiach testowania jednostkowego na Androida, przeczytaj artykuł Co testować.
Lokalizacja testów lokalnych
Domyślnie pliki źródłowe dla lokalnych testów jednostkowych są umieszczane w folderze
module-name/src/test/
Ten katalog jest już utworzony, gdy tworzysz nowy projekt w Android Studio.
Dodaję zależności testowe
Musisz też skonfigurować w projekcie zależności testowe, aby używać parametru dostępnych w środowisku testowym JUnit.
Aby to zrobić, otwórz plik build.gradle
modułu aplikacji i podaj następujące dane
jako zależności. Użyj funkcji testImplementation
, aby wskazać, że te dane dotyczą lokalnego testowego zestawu źródeł, a nie aplikacji:
dependencies {
// Required -- JUnit 4 framework
testImplementation "junit:junit:$jUnitVersion"
// Optional -- Robolectric environment
testImplementation "androidx.test:core:$androidXTestVersion"
// Optional -- Mockito framework
testImplementation "org.mockito:mockito-core:$mockitoVersion"
// Optional -- mockito-kotlin
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
// Optional -- Mockk framework
testImplementation "io.mockk:mockk:$mockkVersion"
}
Tworzenie lokalnej klasy testów jednostkowych
Klasę testu jednostkowego lokalnego piszesz jako klasę testu JUnit 4.
Aby to zrobić, utwórz klasę zawierającą co najmniej 1 metodę testową, zwykle w module-name/src/test/
. Metoda testu zaczyna się od adnotacji @Test
i zawiera kod do testowania i weryfikowania pojedynczego aspektu komponentu, który chcesz przetestować.
Poniższy przykład pokazuje, jak wdrożyć klasę testu jednostkowego lokalnego. Metoda test emailValidator_correctEmailSimple_returnsTrue()
próbuje zweryfikować isValidEmail()
, która jest metodą w aplikacji. Funkcja test zwróci wartość true, jeśli isValidEmail()
zwróci również wartość true.
Kotlin
import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test class EmailValidatorTest { @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() { assertTrue(EmailValidator.isValidEmail("name@email.com")) } }
Java
import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; class EmailValidatorTest { @Test public void emailValidator_CorrectEmailSimple_ReturnsTrue() { assertTrue(EmailValidator.isValidEmail("name@email.com")); } }
Należy tworzyć czytelne testy, które pozwolą ocenić, czy komponenty w tabeli
zwróci oczekiwane wyniki. Zalecamy użycie biblioteki asercji, takiej jak junit.Assert, Hamcrest lub Truth. Powyższy fragment kodu pokazuje, jak za pomocą
junit.Assert
Biblioteka Androida
Podczas wykonywania lokalnych testów jednostkowych wtyczka Gradle dla Androida zawiera bibliotekę z wszystkimi interfejsami API platformy Android w wersji zgodnej z wersją używaną w projekcie. W bibliotece znajdują się wszystkie publiczne metody tych interfejsów API, ale kod wewnątrz metod został usunięty. Jeśli tak, metody, które zostaną użyte, test zgłosi wyjątek.
Umożliwia to tworzenie testów lokalnych w przypadku odwołań do klas w Androidzie.
takiej jak Context
. Co ważniejsze, pozwala ono używać frameworka do symulowania w klasach Androida.
Pozorowanie zależności Androida
Typowym problemem jest to, że klasa używa ciągu znaków. Zasoby ciągu znaków możesz uzyskać, wywołując metodę getString()
w klasie Context
. W teście lokalnym nie można jednak używać właściwości Context
ani żadnej z jej metod, ponieważ
należą do platformy Androida. W idealnej sytuacji wywołanie do getString()
zostałoby przeniesione poza klasę, ale nie zawsze jest to możliwe. Rozwiązaniem jest utworzenie mocka lub stuba Context
, który zawsze zwraca tę samą wartość po wywołaniu metody getString()
.
Dzięki bibliotece Mockable na Androida i ramkom do emulacji takim jak Mockito czy MockK możesz programować zachowanie emulacji klas Androida w testach jednostkowych.
Aby dodać obiekt testowy do lokalnego testu jednostkowego za pomocą Mockito, postępuj zgodnie z tym modelem programowania:
- W pliku
build.gradle
uwzględnij bibliotekę Mockito, jak opisano w artykule Konfigurowanie środowiska testowego. - Na początku definicji klasy testu jednostkowego dodaj
@RunWith(MockitoJUnitRunner.class)
adnotacja. Adnotacja informuje Mockito – uruchom testy do sprawdzenia, czy korzystasz z platformy prawidłowo upraszcza inicjowanie przykładowych obiektów. - Aby utworzyć przykładowy obiekt zależności Androida, dodaj adnotację
@Mock
przed deklaracją pola. - Aby skrócić zachowanie zależności, możesz określić warunek i
zwracana wartość, gdy warunek jest spełniony za pomocą funkcji
when()
ithenReturn()
.
Poniższy przykład pokazuje, jak utworzyć test jednostkowy, który używa obiektu mock Context
w Kotlinie utworzonego za pomocą pakietu Mockito-Kotlin.
import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
private const val FAKE_STRING = "HELLO WORLD"
@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {
@Mock
private lateinit var mockContext: Context
@Test
fun readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
val mockContext = mock<Context> {
on { getString(R.string.name_label) } doReturn FAKE_STRING
}
val myObjectUnderTest = ClassUnderTest(mockContext)
// ...when the string is returned from the object under test...
val result: String = myObjectUnderTest.getName()
// ...then the result should be the expected one.
assertEquals(result, FAKE_STRING)
}
}
Więcej informacji o ramowcu Mockito znajdziesz w dokumentacji interfejsu Mockito API oraz w klasie SharedPreferencesHelperTest
w przykładowym kodzie. Wypróbuj też ćwiczenie z programowania dotyczące testowania aplikacji na Androida.
Błąd: „Metoda ... nie sfałszowana”
Biblioteka aplikacji na Androida zgłasza wyjątek, jeśli spróbujesz uzyskać dostęp do którejkolwiek z jej
z komunikatem Error: "Method ... not mocked
.
Jeśli zgłoszone wyjątki stanowią problem dla Twoich testów, możesz zmienić
w taki sposób, aby metody zwracały wartość null lub zero, w zależności od
zwracany typ. Aby to zrobić, dodaj w pliku build.gradle
na najwyższym poziomie projektu w języku Groovy następującą konfigurację:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}