Automatisation d'applications mobiles sur appareils réels
Mettez en place une automatisation d'applications mobiles fiable sur appareils réels avec Appium, ADB, UIAutomator et XCUITest, avec en plus la gestion de l'instabilité, la parallélisation sur la flotte et l'intégration CI.
L'automatisation d'applications mobiles sur appareils réels utilise des frameworks comme Appium, ADB, UIAutomator et XCUITest pour piloter des téléphones physiques à travers des flux reproductibles. Fonctionner sur du matériel réel — et paralléliser sur une flotte — vous donne une couverture de régression et un signal de performance que les émulateurs ne peuvent pas égaler.
- The core stacks are Appium (cross-platform), UIAutomator/Espresso and ADB (Android), and XCUITest (iOS); scrcpy is invaluable for observing and debugging Android runs.
- Prefer written, versioned scripts over record-and-playback for anything you will maintain; recording is fine for one-off exploration.
- Flakiness is the main enemy — solve it with explicit waits and stable selectors, not sleeps.
- A fleet's value is parallelization: shard suites across devices to keep wall-clock time low.
- Wire automation into CI so every build runs against a real-device core tier.
La pile d'automatisation
Appium
Appium est le choix multiplateforme le plus courant. Il expose le protocole W3C WebDriver, ce qui permet d'écrire les tests dans le langage de son choix et de piloter Android et iOS via une seule API. En coulisses, Appium délègue à des moteurs d'automatisation propres à chaque plateforme — UIAutomator2/Espresso sur Android, XCUITest sur iOS — vous obtenez ainsi un pilotage natif avec une interface portable. Il convient aux équipes qui veulent un seul framework et une seule base de tests sur toutes les plateformes.
ADB (Android Debug Bridge)
ADB est le couteau suisse d'Android. Au-delà de l'installation et du lancement d'applications, il pilote des actions au niveau shell : accorder des permissions, régler le réseau et la langue, simuler des événements d'entrée, capturer le logcat, récupérer des captures d'écran, activer le mode avion et créer des conditions pour les tests. La majorité de l'automatisation Android s'appuie sur ADB pour la configuration initiale, le nettoyage et le contrôle de l'état de l'appareil, même quand le pilotage de l'UI passe par un autre framework.
UIAutomator et Espresso
Pour les équipes uniquement Android, Espresso (en processus, boîte blanche, rapide et stable) couvre l'UI de votre propre application, tandis qu'UIAutomator gère les interactions inter-applications et avec l'UI système (notifications, boîtes de dialogue de permissions, paramètres). Ils sont souvent utilisés ensemble.
XCUITest
XCUITest est le framework UI natif d'Apple, exécuté via Xcode. C'est la voie la plus fiable pour l'automatisation UI sur iOS, et c'est ce qu'Appium pilote en coulisses sur iOS. Pour le comportement spécifique à chaque plateforme et les différences de configuration, voir flottes iOS vs Android.
scrcpy
scrcpy reflète et contrôle un appareil Android via USB ou TCP/IP avec une faible latence. Ce n'est pas un framework de test, mais c'est le moyen le plus rapide d'observer une exécution automatisée, de reproduire un échec de manière interactive et de déboguer des sélecteurs en direct.
| Appium (cross-platform) | Native (Espresso / XCUITest) | |
|---|---|---|
| Codebase | One test suite, both platforms | Separate suite per platform |
| Speed & stability | Good, one layer of indirection | Fastest, most stable on its platform |
| System UI access | Via UIAutomator delegation | Direct (UIAutomator/XCUITest) |
| Best fit | Small team, shared flows | Platform-specific team, max reliability |
Script ou enregistrement
Les outils d'enregistrement-lecture génèrent un script en capturant vos appuis. Ils sont séduisants pour un premier jet ou une vérification ponctuelle, mais les scripts enregistrés ont tendance à être fragiles : ils codent en dur des coordonnées ou des sélecteurs peu robustes et manquent de la structure nécessaire pour être maintenus à grande échelle.
Les scripts écrits à la main l'emportent pour tout ce qui doit durer. Ils permettent d'utiliser des localisateurs stables (identifiants d'accessibilité, ID de ressources), d'extraire des étapes réutilisables, de paramétrer les données, d'ajouter des assertions et de tout conserver dans le contrôle de version aux côtés de l'application. Une voie médiane pratique consiste à enregistrer pour explorer, puis réécrire les flux utiles sous forme de code maintenable avec des sélecteurs et des attentes appropriés.
Lutter contre l'instabilité et la synchronisation
Les tests instables détruisent la confiance dans une suite. Sur des appareils réels, le timing est véritablement variable — la latence réseau, les animations et la charge en arrière-plan fluctuent toutes — la solution est donc une synchronisation rigoureuse.
- N'utilisez jamais de pauses fixes comme mécanisme d'attente principal. Remplacez-les par des attentes explicites qui interrogent une condition (élément présent, visible, activé) jusqu'à un délai maximal.
- Utilisez des sélecteurs stables. Préférez les identifiants d'accessibilité et les ID de ressources à un XPath basé sur le texte ou l'index, qui casse au moindre changement de contenu ou de mise en page.
- Attendez l'état de l'application, pas l'horloge. Les conditions d'inactivité, les signaux de quiescence réseau et les états des éléments sont plus fiables que de deviner une durée.
- Contrôlez l'environnement. Réinitialisez l'état de l'application entre les tests, injectez des données connues, désactivez les animations quand c'est possible, et figez la langue/le fuseau horaire pour que les exécutions soient déterministes.
- Mettez en quarantaine et relancez de façon délibérée. Isolez les tests connus pour être instables, ajoutez des relances bornées pour les étapes véritablement non déterministes, et suivez les taux d'instabilité pour corriger les causes profondes plutôt que de les masquer.
Paralléliser sur une flotte
Un appareil unique exécute les tests en série ; une flotte les exécute en parallèle. C'est la principale raison d'automatiser sur du matériel physique à grande échelle.
Le sharding répartit l'ensemble des tests entre les appareils, de sorte que le temps total diminue de façon à peu près linéaire avec le nombre d'appareils. Vous pouvez répartir par test (répartir les cas de manière équilibrée) ou par cellule de matrice (chaque appareil prend en charge une combinaison OS/modèle de vos niveaux de couverture).
Exigences pratiques pour des exécutions parallèles propres :
| Aspect | Approche |
|---|---|
| Adressage des appareils | Identifiants/numéros de série stables par appareil ; un registre associant les appareils à leurs capacités |
| Isolation | Une session par appareil ; réinitialisation de l'état de l'application entre les exécutions |
| Allocation | Un ordonnanceur qui attribue les appareils libres aux tâches et empêche les doubles réservations |
| Fiabilité | Des contrôles de santé pour que les appareils morts ou hors ligne soient ignorés plutôt que comptés en échec |
Coordonner les attributions, les files d'attente et l'échelonnement relève d'une couche d'orchestration — voir planification et orchestration. Maintenir les appareils suffisamment sains pour faire confiance aux résultats est traité dans supervision et santé de la flotte.
Intégration CI
L'automatisation apporte de la valeur quand elle s'exécute automatiquement. Le schéma type :
- Construire l'artefact de l'application en CI.
- Provisionner un appareil de la flotte via l'ordonnanceur (attribuer un appareil du niveau principal correspondant à la cellule de matrice ciblée).
- Installer et exécuter la suite sur l'appareil attribué.
- Collecter les artefacts — journaux (logcat/syslog), captures d'écran ou vidéo, et un rapport de test structuré.
- Conditionner le pipeline au niveau principal ; exécuter une couverture plus large selon une cadence nocturne ou avant chaque release pour garder un retour rapide sur les PR.
Gardez le provisionnement des appareils derrière l'ordonnanceur plutôt que de coder en dur des numéros de série dans le pipeline, afin que les jobs CI se mettent proprement en file d'attente quand les appareils sont occupés et ne se percutent jamais.
Règle empirique : conditionnez chaque build à une suite de niveau principal petite, rapide et stable. Repoussez la matrice large et lente vers les exécutions nocturnes ou de release. Cela garde le retour aux développeurs rapide sans sacrifier la couverture.