Créer des tests unitaires locaux

Un test local s'exécute directement sur votre propre poste de travail plutôt que sur un appareil Android de votre appareil ou de votre émulateur. Il utilise donc votre machine virtuelle Java (JVM) locale, plutôt qu'un appareil Android pour exécuter des tests. Les tests en local vous permettent d'évaluer la logique de votre application. Toutefois, l'impossibilité d'interagir avec Le framework Android limite les types de tests que vous pouvez exécuter.

Un test unitaire vérifie le comportement d'une petite partie de code, l'unité sous test. Pour ce faire, il exécute ce code et vérifie le résultat.

Les tests unitaires sont généralement simples à configurer, mais leur configuration peut poser problème lorsque le en cours de test n'est pas conçu pour optimiser la testabilité:

  • Le code que vous souhaitez vérifier doit être accessible depuis un test. Pour par exemple, vous ne pouvez pas tester directement une méthode privée. À la place, vous testez la classe à l'aide de ses API publiques.
  • Pour que vous puissiez exécuter des tests unitaires de façon isolée, les dépendances de l'unité doivent être remplacés par des composants que vous contrôlez, tels que des d'autres doubles de test. Cela est particulièrement problématique si votre code dépend le framework Android.

Pour en savoir plus sur les stratégies courantes de tests unitaires dans Android, consultez la section Que faut-il faire ? test.

Emplacement des tests locaux

Par défaut, les fichiers sources des tests unitaires locaux sont placés dans module-name/src/test/ Ce répertoire existe déjà lorsque vous créez à l'aide d'Android Studio.

Ajouter des dépendances de test

Vous devez également configurer les dépendances de test pour que votre projet utilise le API standards fournies par le framework de test JUnit.

Pour ce faire, ouvrez le fichier build.gradle du module de votre application et spécifiez les éléments suivants : les bibliothèques comme dépendances. Utilisez la fonction testImplementation pour indiquer qu'elles s'appliquent à l'ensemble de sources de test local, et non à l'application:

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"
}

Créer une classe de test unitaire local

Vous écrivez votre classe de test unitaire local en tant que classe de test JUnit 4.

Pour ce faire, créez une classe contenant une ou plusieurs méthodes de test, généralement module-name/src/test/ Une méthode de test commence par l'annotation @Test. contient le code permettant de tester et de vérifier un seul aspect du composant que vous souhaitez tester.

L'exemple suivant montre comment implémenter une classe de test unitaire local. La la méthode de test emailValidator_correctEmailSimple_returnsTrue()tente de vérifier isValidEmail(),qui est une méthode intégrée à l'application. La fonction de test renvoie "true" si isValidEmail() renvoie également "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"));
  }
}

Vous devez créer des tests lisibles pour évaluer si les composants de votre l'application renvoie les résultats attendus. Nous vous recommandons d'utiliser une bibliothèque d'assertions comme junit.Assert, Hamcrest ou Faux. L'extrait ci-dessus montre comment utiliser junit.Assert

Bibliothèque Android fictive

Lorsque vous exécutez des tests unitaires locaux, le plug-in Android Gradle inclut un qui contient toutes les API du framework Android, à la utilisée dans votre projet. La bibliothèque contient toutes les méthodes et de ces API, mais le code des méthodes a été supprimé. Le cas échéant des méthodes auxquelles vous accédez, le test génère une exception.

Cela permet de créer des tests en local lors du référencement de classes dans le tel que Context. Mais surtout, elle vous permet d'utiliser avec les classes Android.

Simuler les dépendances Android

Un problème courant consiste à déterminer qu'une classe utilise une ressource de chaîne. Vous pouvez obtenir les ressources de chaîne en appelant la méthode getString() dans Context . Toutefois, un test en local ne peut pas utiliser Context ni aucune de ses méthodes, car appartiennent au framework Android. Dans l'idéal, l'appel à getString() serait retirés de la classe, mais ce n'est pas toujours pratique. La solution est de créez une simulation ou un bouchon de Context qui renvoie toujours la même valeur lorsque son La méthode getString() est appelée.

Avec la bibliothèque Mockable Android et les frameworks de simulation tels que Mockito ou MockK, vous pouvez programmer le le comportement des simulations des classes Android dans vos tests unitaires.

Pour ajouter un objet fictif à votre test unitaire local à l'aide de Mockito, procédez comme suit : de programmation:

  1. Incluez la dépendance de la bibliothèque Mockito dans votre fichier build.gradle, en tant que décrit dans la section Configurer votre environnement de test.
  2. Au début de la définition de votre classe de test unitaire, ajoutez la classe Annotation @RunWith(MockitoJUnitRunner.class). Cette annotation indique au l'exécuteur de test Mockito pour vérifier que votre utilisation du framework est correcte et simplifie l'initialisation de vos objets fictifs.
  3. Pour créer un objet fictif pour une dépendance Android, ajoutez l'annotation @Mock. avant la déclaration du champ.
  4. Pour bouchonner le comportement de la dépendance, vous pouvez spécifier une condition et valeur renvoyée lorsque la condition est remplie à l'aide de when() et thenReturn() méthodes.

L'exemple suivant montre comment créer un test unitaire qui utilise une simulation Objet Context en Kotlin créé avec 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)
  }
}

Pour en savoir plus sur l'utilisation du framework Mockito, consultez la page sur l'API Mockito. référence et la classe SharedPreferencesHelperTest dans exemple de code. Essayez également l'atelier de programmation sur les tests Android.

Erreur : "Méthode ... pas simulée"

La bibliothèque Mockable Android génère une exception si vous essayez d'accéder à l'une de ses avec le message Error: "Method ... not mocked.

Si les exceptions générées posent problème pour vos tests, vous pouvez modifier le de sorte que les méthodes renvoient à la place une valeur nulle ou zéro, en fonction de la type renvoyé. Pour ce faire, ajoutez la configuration suivante dans le fichier Fichier build.gradle de premier niveau en Groovy:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }