Principes de base des tests des applications Android

Cette page décrit les principes de base des tests des applications Android, y compris les les meilleures pratiques et leurs avantages.

Avantages des tests

Les tests font partie intégrante du processus de développement des applications. En effectuant des tests de votre application de manière cohérente, vous pouvez vérifier que celle-ci est correcte, fonctionnelle le comportement et la facilité d'utilisation avant de les rendre publiques.

Vous pouvez tester votre application manuellement en parcourant celle-ci. Vous pourriez utiliser différents appareils et émulateurs, changer la langue du système et essayer de générer chaque erreur utilisateur ou de traverser chaque flux utilisateur.

Toutefois, les tests manuels sont peu performants et peuvent être facilement négligés. des régressions dans le comportement de votre application. Les tests automatisés impliquent l'utilisation d'outils qui effectuent des tests à votre place, qui sont plus rapides, plus reproductibles et généralement vous fournit des commentaires plus exploitables concernant votre application plus tôt dans le développement ; processus.

Types de tests dans Android

Les applications mobiles sont complexes et doivent bien fonctionner dans de nombreux environnements. En tant que il existe de nombreux types de tests.

Objet

Par exemple, il existe différents types de tests selon le sujet:

  • Tests fonctionnels: mon application fait-elle ce qu'elle est censée faire ?
  • Tests de performances: le processus est-il rapide et efficace ?
  • Tests d'accessibilité: fonctionnent-ils bien avec les services d'accessibilité ?
  • Tests de compatibilité: fonctionnent-ils bien sur tous les appareils et niveaux d'API ?

Champ d'application

Les tests varient également en fonction de la taille ou du degré d'isolation:

  • Les tests unitaires ou les tests petits ne vérifient qu'une très petite partie de l'application. comme une méthode ou une classe.
  • Les tests de bout en bout ou les tests volumineux vérifient des parties plus importantes de l'application au niveau en même temps, comme un écran entier ou un flux utilisateur.
  • Les tests moyens se situent entre les deux et vérifient l'intégration entre deux unités supplémentaires.
<ph type="x-smartling-placeholder">
</ph> Les tests peuvent être petits, moyens ou grands.
Figure 1: Tester les champs d'application dans une application type

Il existe de nombreuses façons de classer les tests. Toutefois, la distinction la plus importante pour les développeurs d'applications est l'endroit où les tests sont exécutés.

Tests instrumentés et tests en local

Vous pouvez exécuter des tests sur un appareil Android ou sur un autre ordinateur:

  • Les tests d'instrumentation s'exécutent sur un appareil Android, qu'ils soient physiques ou émulés. L'application est créée et installée en même temps qu'une application de test qui injecte des commandes et lit l'état. Les tests d'instrumentation sont généralement des tests d'interface utilisateur, puis interagir avec elle.
  • Les tests en local s'exécutent sur votre ordinateur de développement ou sur un serveur. également appelés tests côté hôte. Ils sont généralement petits et rapides, isolant le sujet testé dans le reste de l'application.
<ph type="x-smartling-placeholder">
</ph> Les tests peuvent s&#39;exécuter en tant que tests d&#39;instrumentation sur un appareil ou en local sur votre ordinateur de développement.
Figure 2: Différents types de tests en fonction de l'emplacement d'exécution

Tous les tests unitaires ne sont pas locaux, et tous les tests de bout en bout ne sont pas exécutés sur un appareil. Exemple :

  • Test local de grande envergure: vous pouvez utiliser un simulateur Android qui s'exécute en local, tel que en tant que Robolectric.
  • Petit test d'instrumentation: vous pouvez vérifier que votre code fonctionne correctement avec un comme une base de données SQLite. Vous pouvez exécuter ce test sur plusieurs appareils pour vérifier l'intégration avec plusieurs versions de SQLite.

Exemples

Les extraits de code suivants montrent comment interagir avec l'interface utilisateur dans un test d'interface utilisateur d'instrumentation qui clique sur un élément et vérifie qu'un autre s'affiche.

Espresso

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

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

Compose UI

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

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

Cet extrait montre une partie d'un test unitaire pour un ViewModel (local, côté hôte) test):

// 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)

Définir une stratégie de test

Dans un monde idéal, vous testeriez chaque ligne de code de votre application sur chaque appareil. compatibles avec votre application. Malheureusement, cette approche est trop lente et coûteux en termes de réalisabilité.

Une stratégie de test efficace permet de trouver un équilibre sa vitesse et sa fiabilité. La similitude de l'environnement de test avec un appareil réel détermine la fidélité du test. Les tests de haute-fidélité sont exécutés sur des appareils émulés ou l'appareil physique lui-même. Des tests de basse fidélité peuvent être exécutés sur la JVM de votre poste de travail local. Les tests haute-fidélité sont souvent plus lents et nécessitent plus de ressources, donc tous les tests ne doivent pas être un test haute-fidélité.

Tests irréguliers

Les erreurs se produisent même dans des exécutions de test correctement conçues et implémentées. Par exemple : lors de l'exécution d'un test sur un appareil réel, une mise à jour automatique peut démarrer dans le au milieu d'un test et de faire échouer celui-ci. Des conditions de concurrence subtiles dans votre code peuvent ne se produisent qu'un peu du temps. Les tests qui ne réussissent pas 100% des tests au fil du temps sont instables.

Architecture testable

Avec une architecture d'application testable, le code suit une structure qui vous permet pour tester facilement différentes parties de celui-ci de façon isolée. Les architectures testables comportent d'autres avantages, tels qu'une meilleure lisibilité, une meilleure gestion, une évolutivité la réutilisabilité.

Une architecture non testable produit les éléments suivants:

  • Tests plus volumineux, plus lents et plus irréguliers. Les classes qui ne peuvent pas faire l'objet de tests unitaires peuvent comporter être couverts par des tests d'intégration plus importants ou des tests d'interface utilisateur.
  • Moins d'occasions de tester différents scénarios. Les tests plus importants sont plus lents, Il peut donc être irréaliste de tester tous les états possibles d'une application.

Pour en savoir plus sur les consignes relatives à l'architecture, consultez le guide des applications architecture.

Approches du découplage

S'il est possible d'extraire une partie d'une fonction, d'une classe ou d'un module du reste, il est plus facile et plus efficace. Cette pratique est connue sous le nom de découplage et elle est le concept le plus important pour une architecture testable.

Les techniques de découplage courantes sont les suivantes:

  • Diviser une application en couches telles que Présentation, Domaine et Données. Vous pouvez Diviser également l'application en modules, un par fonctionnalité
  • Évitez d'ajouter une logique à des entités qui ont de grandes dépendances, telles que les activités et les fragments. Utilisez ces classes comme points d'entrée du framework et déplacer l'UI et la logique métier ailleurs, par exemple vers un composable, un ViewModel ou la couche de domaine.
  • Évitez les dépendances de framework directes dans les classes contenant une logique métier. Par exemple, n'utilisez pas de contextes Android dans les ViewModels.
  • Simplifiez le remplacement des dépendances. Par exemple, utilisez interfaces plutôt que des implémentations concrètes. Utilisez Injection de dépendances, même si vous n'utilisez pas de framework d'injection de dépendances.

Étapes suivantes

Maintenant que vous savez pourquoi vous devriez effectuer des tests et que vous connaissez les deux principaux types de tests, vous pouvez consultez la section Éléments à tester.

Si vous voulez créer votre premier test et apprendre par la pratique, les ateliers de programmation sur les tests.