UI Automator est un framework de Google pour les tests UI automatisés des applications Android qui fonctionne au niveau du système et peut interagir avec les éléments d’interface au-delà d’une seule application. Contrairement à Espresso, UI Automator n’est pas lié au processus d’une application spécifique : il peut ouvrir les dialogues système, le panneau de notifications et basculer entre les applications. Selon Google Android Developers, UI Automator utilise le Accessibility Service standard pour accéder à l’arborescence UI de l’appareil.
Points clés
UI Automator est un framework pour les tests UI fonctionnels d’Android qui fonctionne au niveau du système d’exploitation. Il fournit une API pour accéder à tout élément sur l’écran de l’appareil, quelle que soit l’application à laquelle il appartient — y compris la barre d’état système, les dialogues de permissions, l’écran d’accueil et les applications tierces. Cela le rend indispensable pour tester des scénarios qui dépassent le cadre d’une seule application.
Architecturalement, UI Automator utilise le Accessibility Service — le même service utilisé par TalkBack, Switch Access et d’autres outils d’accessibilité. Grâce à ce service, le framework obtient l’arborescence complète des composants UI de l’écran actuel et permet d’effectuer des actions sur eux : appuyer, glisser, saisir du texte et appuyer longuement.
UI Automator est apparu pour la première fois dans Android 4.3 (API 18) et fait depuis partie de l’Android Testing Support Library en tant qu’outil officiel de Google pour les tests inter-applications. Dans AndroidX Test, il est disponible en tant qu’artefact séparé androidx.test.uiautomator:uiautomator version 2.3.0 (2024), qui prend en charge toutes les versions d’Android depuis l’API 18.
Principe de fonctionnement : UI Automator repose sur l’analyse de l’arborescence d’accessibilité de l’écran actuel. Lorsque la méthode findObject(selector) est appelée, le framework parcourt la hiérarchie des vues, trouve le premier élément correspondant aux conditions de UiSelector et renvoie un objet UiObject — un proxy pour interagir avec la vue réelle.
Un test UI Automator typique commence par l’obtention d’une instance de UiDevice, qui représente l’appareil physique. UiDevice fournit des méthodes pour trouver des éléments, gérer les pressions de boutons (Accueil, Retour, Récents), faire pivoter l’écran et prendre des captures d’écran. Après avoir trouvé un élément via UiSelector, des actions sont effectuées sur l’UiObject.
Dans l’exemple ci-dessous, le test ouvre l’application Paramètres, trouve l’élément « Batterie » par son texte et appuie dessus. UI Automator ne nécessite pas de lancer une activité — il fonctionne avec n’importe quel écran de l’appareil, y compris les applications tierces.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Ouvrir l’écran des paramètres
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Paramètres")), 2000)
// Trouver l’élément « Batterie » et appuyer
val batteryItem = device.findObject(
UiSelector().text("Batterie")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice est la classe principale pour interagir avec l’appareil. Elle fournit des méthodes pour trouver des éléments, simuler des pressions de boutons matériels (Accueil, Retour, Menu, Volume), gérer l’alimentation, prendre des captures d’écran et attendre des états d’écran spécifiques. UiDevice est créé une fois par test et réutilisé pour toutes les opérations.
UiSelector est une API fluide pour trouver des éléments UI. Contrairement aux ViewMatchers d’Espresso, UiSelector ne nécessite pas de compilation — les conditions de recherche sont formées via une chaîne de méthodes : text(), className(), description(), resourceId(), index(). Plusieurs conditions sont combinées automatiquement via un ET logique.
| Méthode UiSelector | Objectif |
|---|---|
| text(String) | Recherche par texte exact de l’élément |
| textContains(String) | Recherche par correspondance partielle de texte |
| resourceId(String) | Recherche par ID de ressource (ex. com.example:id/button) |
| className(String) | Recherche par nom de classe de la vue |
| description(String) | Recherche par content-description |
| childSelector(selector) | Recherche d’un élément enfant dans un conteneur |
Lorsque plusieurs éléments sur l’écran partagent le même texte, UiSelector permet de combiner des critères : trouver un conteneur par son ID, puis à l’intérieur — un élément par texte et classe. Cela garantit une identification unique du composant souhaité. La méthode childSelector réduit la portée de la recherche à un conteneur spécifique, accélérant la navigation dans l’arborescence UI.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// Dans la liste, trouver l’élément avec le texte « Wi-Fi »
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Les tests inter-applications (cross-application) sont la fonctionnalité principale pour laquelle UI Automator est choisi. Le framework peut basculer entre les applications, tester la connexion OAuth via un navigateur, vérifier les dialogues système (permissions, sélecteur d’application) et interagir avec la barre d’état système, le panneau de notifications et l’écran de verrouillage.
Un scénario typique de test inter-applications : l’application ouvre un navigateur pour l’autorisation OAuth, l’utilisateur saisit son identifiant et son mot de passe, et le navigateur redirige vers l’application. UI Automator bascule entre les processus, trouve les champs de saisie dans le navigateur, les remplit et appuie sur « Connexion ».
// Attente de l’apparition du navigateur
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// Recherche du champ de saisie d’e-mail dans le navigateur
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
UI Automator peut vérifier et fermer les dialogues système — permissions de localisation, notifications, accès aux fichiers. C’est crucial pour tester les scénarios de premier lancement lorsque le système demande plusieurs permissions séquentiellement. Sans UI Automator, ces scénarios ne peuvent pas être automatisés car les dialogues système n’appartiennent pas au processus de l’application.
Le choix entre UI Automator et Espresso dépend du scénario de test. Espresso est optimisé pour tester une seule application avec synchronisation automatique et un minimum de code passe-partout. UI Automator convient aux scénarios où il est nécessaire d’interagir avec le système, le navigateur ou plusieurs applications.
| Critère | UI Automator | Espresso |
|---|---|---|
| Portée | Appareil entier, plusieurs applications | Une seule application |
| Synchronisation | Manuelle (attente, pause) | Automatique (Idling Resource) |
| Vitesse | Plus lent (accès via service) | Plus rapide (fonctionne dans le processus) |
| UI système | Prend en charge (Notifications, Paramètres rapides) | Ne prend pas en charge |
| Précision de recherche | UiSelector par attributs | ViewMatchers par type et hiérarchie |
| Stabilité | Inférieure (dépend du timing) | Supérieure (attente automatique) |
En pratique, ces frameworks sont souvent utilisés ensemble : Espresso couvre les tests UI de l’application principale avec une grande stabilité, tandis qu’UI Automator est utilisé pour les scénarios qui dépassent les limites de l’application — connexion OAuth, permissions système, travail avec Share Intent. Cette combinaison offre une couverture UI maximale avec des coûts de maintenance de tests minimaux.
L’intégration d’UI Automator se fait en ajoutant une dépendance dans build.gradle. Le framework fait partie d’AndroidX Test et ne nécessite pas de permissions supplémentaires dans le manifeste — l’accès au Accessibility Service est configuré automatiquement lors du lancement du test instrumenté.
La configuration minimale inclut l’artefact uiautomator et l’exécuteur de tests standard AndroidJUnitRunner. Les tests UI Automator sont placés dans le répertoire src/androidTest et exécutés sur un émulateur ou un appareil physique fonctionnant sous Android API 18+.
dependencies {
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test:runner:1.6.1")
}
Pour obtenir une instance de UiDevice, on utilise InstrumentationRegistry.getInstrumentation(). UiDevice doit être créé une fois dans la méthode setUp() et réutilisé dans tous les tests de la classe pour économiser les ressources de l’appareil. Il est important de noter que UiDevice n’est pas thread-safe — toutes les opérations doivent être exécutées dans le même thread que la méthode de test. Créer un nouveau UiDevice dans chaque test génère une surcharge et ralentit l’exécution. Il est recommandé de créer UiDevice une fois dans la méthode beforeClass et de le réutiliser pour tous les tests de la classe de test.
Contrairement à Espresso, UI Automator n’a pas de synchronisation automatique. Pour attendre l’apparition d’éléments, on utilise la méthode UiDevice.wait(condition, timeout) avec un objet Until : Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Sans attentes appropriées, les tests deviennent instables en raison de conditions de concurrence — un élément peut ne pas être apparu à l’écran au moment de la recherche. Il est recommandé de définir un délai d’attente d’au moins 3 à 5 secondes pour la stabilité.
Questions fréquentes
UI Automator fonctionne au niveau du Accessibility Service et peut interagir avec n’importe quelle application. Espresso fonctionne au sein du processus d’une seule application et utilise la synchronisation automatique avec le thread UI. UI Automator est meilleur pour les scénarios inter-applications, tandis qu’Espresso est meilleur pour les tests stables d’une seule application.
Oui, UI Automator fonctionne sur tous les appareils sous Android API 18+. Il ne nécessite pas d’accès root — il utilise le Accessibility Service standard, qui est activé via Instrumentation au lancement des tests.
UI Automator utilise le Accessibility Service pour obtenir l’arborescence complète des composants UI de l’écran actuel. Ensuite, UiSelector parcourt cette arborescence et trouve les éléments selon les critères spécifiés : texte, classe, ID, content-description ou une combinaison de ceux-ci.
Oui, la méthode UiDevice.takeScreenshot(storePath) permet de prendre une capture d’écran de l’écran actuel et de la sauvegarder dans un fichier. Ceci est utile pour le débogage : lorsqu’un test échoue, vous pouvez sauvegarder la capture d’écran et analyser l’état de l’écran.
UI Automator n’a pas de synchronisation automatique, donc les tests sont sensibles au timing. Si une animation n’est pas terminée ou si une vue n’a pas encore été rendue, findObject peut ne pas trouver l’élément. La solution est d’utiliser UiDevice.wait() avec un délai d’attente suffisant.
Résumé
La suite d’outils UI Automator couvre tous les scénarios clés de tests inter-applications et constitue la norme pour l’automatisation Android au niveau du système.
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi