Chapitre 1 – Introduction à Appium
Pourquoi Appium ?
Appium est un framework d'automatisation de tests open source, conçu pour tester des applications mobiles (Android et iOS). Contrairement à d'autres outils d'automatisation, il a été pensé dès le départ pour être agnostique du langage de programmation et de la plateforme. Cette approche universelle représente une véritable révolution dans le monde des tests mobiles.
L'originalité d'Appium réside dans sa philosophie : permettre aux développeurs et testeurs d'utiliser leurs compétences existantes, quel que soit leur langage de prédilection. Vous maîtrisez Java ? Parfait. Vous préférez Python ou C# ? Aucun problème. Cette flexibilité évite l'apprentissage d'outils propriétaires spécifiques à chaque plateforme.
Concrètement, cela signifie que :
- Vous pouvez écrire vos tests en Java, Python, JavaScript, Ruby, C#, et même en langages plus exotiques
- Vous pouvez les exécuter sur Android comme sur iOS, sans réécrire la logique métier
- Votre équipe peut continuer à utiliser ses outils et frameworks de test favoris (JUnit, TestNG, pytest, etc.)
- L'investissement en formation est minimisé car les concepts de base restent les mêmes
L'idée originelle d'Appium est : « automatiser tout ce qui se fait à la main sur un téléphone, sans modifier l'application ». Cette approche non-intrusive garantit que vos tests reflètent réellement l'expérience utilisateur.
Cas d'usage concrets
Dans le paysage actuel du développement mobile, les applications se déclinent en trois grandes familles, chacune ayant ses spécificités techniques et ses enjeux de test. Appium excelle dans l'automatisation de toutes ces catégories.
1. Applications natives
Les applications natives sont développées directement dans les langages et SDK officiels des plateformes : Java ou Kotlin pour Android, Swift ou Objective-C pour iOS. Ces applications offrent généralement les meilleures performances et l'accès le plus complet aux fonctionnalités du système (caméra, GPS, notifications push, etc.).
Avec Appium, vous pouvez tester ces applications en utilisant les mêmes mécanismes que les frameworks natifs : UiAutomator2 sur Android et XCUITest sur iOS. Cela garantit une fidélité maximale dans la simulation des interactions utilisateur.
2. Applications web mobiles
Ces applications sont des sites web optimisés pour mobile, accessibles via le navigateur. Bien qu'elles ne bénéficient pas de toutes les capacités natives, elles présentent l'avantage d'une maintenance simplifiée et d'un déploiement universel.
Appium peut piloter Chrome Mobile, Safari Mobile, ou tout autre navigateur mobile, en s'appuyant sur les drivers Selenium sous-jacents. Vous retrouvez ainsi tous vos réflexes de test web, adaptés à l'écran tactile.
3. Applications hybrides
Les applications hybrides combinent le meilleur des deux mondes : une partie web (HTML/CSS/JavaScript) encapsulée dans une coque native. Des frameworks comme Ionic, Cordova, React Native ou Flutter permettent de développer une fois et de déployer sur plusieurs plateformes.
Appium gère parfaitement ces cas complexes en permettant de basculer entre le contexte natif (pour les menus, barres de navigation) et le contexte web (pour le contenu applicatif). Cette capacité de switching contextuel est unique dans l'écosystème des outils de test.
Architecture technique d'Appium
Pour comprendre la puissance et les limites d'Appium, il est essentiel de maîtriser son architecture. Contrairement aux outils de test traditionnels qui s'exécutent directement sur la machine de test, Appium repose sur une architecture client/serveur distribuée.
Le serveur Appium : le chef d'orchestre
Le serveur Appium est une application Node.js qui fait office d'intermédiaire intelligent entre vos scripts de test et les appareils mobiles. Il expose une API REST conforme au protocole WebDriver W3C, garantissant une compatibilité maximale avec l'écosystème Selenium existant.
Ce serveur ne se contente pas de transmettre bêtement les commandes : il les traduit, les optimise, et gère les spécificités de chaque plateforme. Par exemple, une commande de clic sera traduite différemment selon qu'elle s'adresse à un émulateur Android ou à un iPhone physique.
Le client Appium : votre interface de développement
Votre script de test (le client) communique avec le serveur via des requêtes HTTP standard. Cette approche présente plusieurs avantages majeurs :
- Langage-agnostic : n'importe quel langage capable de faire des requêtes HTTP peut piloter Appium
- Réseau-friendly : le serveur peut tourner sur une machine distante, idéal pour les fermes de test
- Debug-friendly : toutes les communications sont loggées et peuvent être inspectées
- Standard-compliant : respect du protocole WebDriver, garantissant la pérennité
Les drivers natifs : l'exécution réelle
Au bout de la chaîne, Appium s'appuie sur les frameworks d'automatisation officiels de chaque plateforme. Cette approche garantit une fidélité maximale et une évolution synchrone avec les OS mobiles :
- Android : UiAutomator2 (recommandé) ou Espresso pour les tests plus fins
- iOS : XCUITest, le framework officiel d'Apple depuis iOS 9
- Windows : WinAppDriver pour les applications UWP
Flux d'exécution concret
Prenons un exemple pratique pour illustrer ce flux : votre test Java veut cliquer sur un bouton "Connexion".
- Étape 1 : Votre code Java envoie une requête POST à
http://localhost:4723/session/:id/element/:elementId/click - Étape 2 : Le serveur Appium reçoit cette requête et l'analyse
- Étape 3 : Le serveur traduit cette commande en instruction UiAutomator2 :
element.click() - Étape 4 : UiAutomator2 exécute réellement le clic sur l'appareil Android
- Étape 5 : Le résultat remonte la chaîne jusqu'à votre test Java
Installation & Configuration
Prérequis : la fondation de votre environnement Appium
L'installation d'Appium peut sembler straightforward, mais la réalité du terrain montre que la majorité des échecs proviennent d'un environnement de développement mal préparé. Cette section détaille méthodiquement chaque prérequis, en expliquant non seulement le "comment" mais aussi le "pourquoi" de chaque composant.
Appium s'appuie sur un écosystème complexe de technologies interdépendantes. Une défaillance dans l'un des maillons peut rendre l'ensemble inutilisable. Cette interdépendance explique pourquoi l'installation d'Appium nécessite plus de rigueur que celle d'un simple outil de développement classique.
1. Java JDK : le socle technique incontournable
Java occupe une position centrale dans l'écosystème Appium, et ce pour plusieurs raisons techniques fondamentales. Premièrement, les outils de développement Android (SDK, Android Studio, outils de build) sont majoritairement écrits en Java. Deuxièmement, de nombreux composants d'Appium utilisent la JVM comme plateforme d'exécution.
Le choix de la version Java n'est pas anodin et impacte directement la stabilité de votre environnement. Java 11 et Java 17 sont les versions LTS (Long Term Support) recommandées car elles offrent le meilleur équilibre entre stabilité, support communautaire, et compatibilité avec l'écosystème Android.
Java 8, bien qu'encore utilisé dans certains contextes, devient progressivement obsolète et pose des problèmes de compatibilité avec les versions récentes d'Android Studio et Gradle. À l'inverse, les versions plus récentes (Java 19, 20, 21) peuvent introduire des incompatibilités avec certains plugins Maven ou outils de build.
Procédure d'installation Java :
- Téléchargez le JDK depuis Adoptium (Eclipse Temurin) ou Oracle. Adoptium est généralement préférable car il s'agit d'une distribution OpenJDK certifiée et gratuite.
- Lors de l'installation, assurez-vous de cocher "Add to PATH" si l'option est disponible
- Configurez la variable d'environnement
JAVA_HOMEpour pointer vers le répertoire d'installation du JDK
Configuration des variables d'environnement :
# Windows (dans les Variables d'environnement système)
JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-17.0.8.7-hotspot
# macOS (dans ~/.bash_profile ou ~/.zshrc)
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
# Linux (dans ~/.bashrc ou ~/.profile)
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
Validation de l'installation :
java -version
# Sortie attendue : openjdk version "17.0.8" 2023-07-18
javac -version
# Sortie attendue : javac 17.0.8
java -version et javac -version retournent des versions différentes,
cela indique un problème de PATH ou plusieurs installations Java conflictuelles. Utilisez which java (Unix)
ou where java (Windows) pour identifier le problème.
2. Maven : orchestrateur de votre projet
Maven dépasse le simple rôle de gestionnaire de dépendances pour devenir le chef d'orchestre de votre projet de test. Il standardise la structure des projets, automatise les tâches de build, gère les versions des bibliothèques, et facilite l'intégration avec les outils de CI/CD.
L'avantage de Maven dans le contexte Appium est triple. D'abord, il simplifie drastiquement la gestion des dépendances :
plus besoin de télécharger manuellement les JAR d'Appium, Selenium, TestNG, etc. Ensuite, il standardise l'exécution des tests
via la commande mvn test, indépendamment de l'IDE utilisé. Enfin, il facilite l'intégration continue
en fournissant des rapports standardisés (Surefire, etc.).
Installation de Maven :
- Téléchargez la dernière version depuis maven.apache.org
- Décompressez l'archive dans un répertoire sans espaces (ex: C:\tools\maven sur Windows)
- Ajoutez le répertoire
binde Maven à votre PATH - Créez la variable d'environnement
M2_HOMEpointant vers le répertoire Maven
Validation de Maven :
mvn -version
# Sortie attendue :
# Apache Maven 3.9.4
# Maven home: /opt/maven
# Java version: 17.0.8, vendor: Eclipse Adoptium
3. Node.js : le runtime du serveur Appium
Appium Server est entièrement développé en JavaScript et s'exécute sur Node.js. Cette architecture présente plusieurs avantages : développement rapide, communauté active, écosystème npm riche, et portabilité cross-platform native.
Le choix de la version Node.js est crucial pour la stabilité. Les versions LTS (Long Term Support) sont toujours préférables car elles bénéficient de corrections de bugs et de mises à jour de sécurité pendant une durée étendue. Les versions "Current" peuvent contenir des fonctionnalités expérimentales susceptibles de créer des instabilités.
Installation Node.js :
- Rendez-vous sur nodejs.org et téléchargez la version LTS
- Utilisez l'installateur officiel plutôt que les gestionnaires de paquets tiers (évite les problèmes de permissions)
- Sur Windows, évitez absolument l'installation via Microsoft Store (problèmes connus avec npm)
Validation Node.js :
node -v
# Sortie attendue : v18.17.1 (ou version LTS actuelle)
npm -v
# Sortie attendue : 9.6.7 (ou version associée)
Installation d'Appium et outils associés :
# Installation globale d'Appium
npm install -g appium
# Installation d'Appium Doctor pour le diagnostic
npm install -g appium-doctor
# Installation du driver Android (optionnel, installé par défaut)
appium driver install uiautomator2
# Installation du driver iOS (si nécessaire)
appium driver install xcuitest
Test de l'installation Appium :
# Vérifier la version d'Appium
appium -v
# Sortie attendue : 2.2.1 (ou version actuelle)
# Diagnostic complet de l'environnement Android
appium-doctor --android
# Doit afficher toutes les vérifications en vert ✓
4. Android Studio : portail vers l'écosystème Android
Android Studio n'est pas seulement un IDE de développement, c'est la porte d'entrée officielle vers tout l'écosystème Android. Il embarque le SDK Android, les outils de debugging (ADB), l'émulateur, et les outils de build (Gradle). Même si vous ne développez pas d'applications Android, ces composants sont indispensables pour Appium.
L'Android SDK contient les bibliothèques et outils nécessaires pour communiquer avec les appareils Android. ADB (Android Debug Bridge) est l'outil en ligne de commande qui permet de contrôler les appareils et émulateurs. L'émulateur Android vous permettra de tester sans appareil physique, ce qui est particulièrement utile pour l'intégration continue.
Installation Android Studio :
- Téléchargez Android Studio depuis developer.android.com
- Lors de l'installation, assurez-vous de sélectionner :
- Android SDK : bibliothèques de développement
- Android SDK Platform-Tools : contient ADB
- Android Emulator : émulateur officiel
- Android Virtual Device : gestionnaire d'émulateurs
Configuration post-installation :
Après l'installation d'Android Studio, ouvrez le SDK Manager (Tools > SDK Manager) et installez :
- Android API 30 (Android 11) ou supérieur : versions récentes pour la compatibilité
- Android API 28-29 : versions antérieures pour la rétrocompatibilité
- Google Play Services : pour tester les applications utilisant les services Google
- Google USB Driver (Windows uniquement) : pour connecter des appareils physiques
Configuration des variables d'environnement Android :
# Windows
ANDROID_HOME=C:\Users\[USERNAME]\AppData\Local\Android\Sdk
PATH=%PATH%;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\emulator
# macOS
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator
# Linux
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator
Validation de l'installation Android :
# Vérifier ADB
adb --version
# Sortie attendue : Android Debug Bridge version 1.0.41
# Lister les appareils connectés
adb devices
# Doit fonctionner sans erreur (liste vide si aucun appareil connecté)
# Vérifier l'émulateur
emulator -list-avds
# Doit lister les AVDs créés (peut être vide initialement)
Validation finale de l'environnement
Une fois tous les composants installés, la validation finale via Appium Doctor vous donnera un diagnostic complet de votre environnement. Cette étape est cruciale car elle détecte les problèmes de configuration avant qu'ils ne causent des échecs de tests mystérieux.
# Diagnostic complet pour Android
appium-doctor --android
# Si vous travaillez aussi sur iOS (Mac uniquement)
appium-doctor --ios
Appium Doctor vérifie systematiquement :
- Présence et version de Java, Node.js, npm
- Reproductibilité : configuration identique entre tous les environnements de test
- Économie : pas d'investissement en hardware physique
- Parallélisation : possibilité de lancer plusieurs instances simultanément
- Contrôle complet : simulation de conditions réseau, batterie, localisation GPS
- Intégration CI/CD : parfait pour l'automatisation complète
- Reset facile : retour à un état propre en quelques secondes
- Performance : généralement plus lents que les appareils physiques
- Fidélité limitée : certains comportements hardware non simulés
- Consommation ressources : utilisation intensive CPU/RAM de la machine hôte
- Limitations capteurs : caméra, NFC, certains capteurs indisponibles
- Ouvrir Android Studio et naviguer vers Tools > Device Manager
- Cliquer sur "Create Device" pour lancer l'assistant de création
- Sélection du hardware :
- Privilégier les profils Pixel (Pixel 4, Pixel 6, Pixel 7) pour leur compatibilité optimale
- Éviter les profils avec trop de RAM (>4GB) qui ralentissent la machine hôte
- Pour les tablettes, Pixel C ou Nexus 10 sont de bons compromis
- Sélection de l'image système :
- API Level 30 (Android 11) ou API 33 (Android 13) pour la modernité
- Target x86_64 pour les meilleures performances sur PC Intel/AMD
- Google APIs si vous testez des apps utilisant les services Google
- Éviter les images ARM sur machine x86 (très lent par émulation)
- Configuration avancée :
- RAM : 2048-4096 MB (équilibre performance/ressources)
- Storage interne : 8GB minimum, 16GB recommandé
- Graphics : Hardware GLES 2.0 si supporté, Software sinon
- Boot option : Cold boot (plus stable pour les tests)
Émulateurs & Appareils physiques : choisir la bonne stratégie de test
Le choix entre émulateurs et appareils physiques constitue l'une des décisions stratégiques majeures dans la mise en place de tests Appium. Chaque approche présente des avantages et inconvénients qu'il convient de comprendre pour optimiser votre stratégie de test.
Émulateurs Android : la puissance de la virtualisation
Les émulateurs Android (AVD - Android Virtual Device) sont des machines virtuelles qui simulent un appareil Android complet sur votre ordinateur. Cette approche offre une flexibilité exceptionnelle pour les tests automatisés, particulièrement dans les environnements de développement et d'intégration continue.
Avantages des émulateurs :
Inconvénients des émulateurs :
Création d'un émulateur Android optimisé :
La création d'un émulateur efficace nécessite un équilibre entre performance et fidélité. Voici la procédure détaillée pour créer un AVD optimisé pour les tests Appium :
Validation de l'émulateur :
# Lancer l'émulateur depuis la ligne de commande
emulator -avd Pixel_4_API_33
# Dans un autre terminal, vérifier la détection
adb devices
# Sortie attendue : emulator-5554 device
# Vérifier les capacités de l'émulateur
adb shell getprop ro.build.version.release
# Sortie attendue : 13 (pour Android 13)
Appareil Android physique : fidélité maximale
Tester sur un appareil Android physique reste indispensable pour valider le comportement réel de votre application. Les différences entre émulation et réalité peuvent être subtiles mais critiques : performances réelles, comportements des capteurs, interactions avec le système, gestion des notifications, etc.
Activation du mode développeur :
Cette procédure est identique sur la plupart des appareils Android, mais peut varier légèrement selon les constructeurs :
- Ouvrir Paramètres > À propos du téléphone (ou "À propos de l'appareil")
- Rechercher "Numéro de build" ou "Version du logiciel"
- Taper 7 fois rapidement sur cette entrée
- Un message confirme l'activation : "Vous êtes maintenant un développeur"
- Retourner dans Paramètres : un nouveau menu "Options pour les développeurs" apparaît
Configuration du débogage USB :
- Dans "Options pour les développeurs", activer "Débogage USB"
- Optionnel mais recommandé : activer "Rester éveillé" (évite la veille pendant les tests)
- Connecter l'appareil via USB à l'ordinateur
- Une popup apparaît sur l'appareil : "Autoriser le débogage USB ?"
- Cocher "Toujours autoriser depuis cet ordinateur" et valider
Résolution des problèmes de connexion :
La connexion d'appareils physiques peut poser des défis spécifiques selon l'OS et le constructeur :
Sur Windows :
- Installer les pilotes USB spécifiques au constructeur (Samsung, Xiaomi, OnePlus, etc.)
- Les pilotes "universels" de Windows ne suffisent généralement pas
- En cas d'échec, utiliser les pilotes génériques Google USB depuis Android Studio
Sur macOS :
- Généralement plug-and-play, pas de pilotes supplémentaires nécessaires
- En cas de problème, vérifier les autorisations de sécurité macOS
Sur Linux :
- Configurer les règles udev pour les permissions USB
- Ajouter l'utilisateur au groupe "plugdev"
- Redémarrer le service udev :
sudo service udev restart
Validation de la connexion :
# Vérifier la détection de l'appareil
adb devices
# Sortie attendue : R58M12345X device (pas unauthorized)
# Tester la communication
adb shell echo "Test de connexion"
# Doit retourner : Test de connexion
# Vérifier les informations système
adb shell getprop ro.product.model
# Retourne le modèle de l'appareil
Configuration iOS : écosystème Apple
L'automatisation iOS avec Appium nécessite un environnement macOS et présente des défis spécifiques liés aux politiques de sécurité d'Apple. Cette section détaille les prérequis et procédures pour iOS.
Simulateur iOS : l'émulation officielle Apple
Contrairement à Android où les émulateurs sont des machines virtuelles complètes, les simulateurs iOS sont des environnements d'exécution natifs qui simulent l'interface utilisateur d'iOS sur macOS. Cette approche offre d'excellentes performances mais avec certaines limitations fonctionnelles.
Installation et configuration Xcode :
- Installer Xcode depuis l'App Store (installation longue, ~10GB)
- Lancer Xcode une première fois pour finaliser l'installation
- Accepter les termes de licence :
sudo xcodebuild -license accept - Ouvrir Xcode > Preferences > Platforms
- Télécharger les simulateurs iOS souhaités (iOS 15, 16, 17)
Gestion des simulateurs iOS :
# Lister tous les simulateurs disponibles
xcrun simctl list devices
# Créer un nouveau simulateur personnalisé
xcrun simctl create "iPhone14-Test" "iPhone 14" "iOS16.0"
# Lancer un simulateur spécifique
xcrun simctl boot "iPhone 14"
open -a Simulator
# Vérifier les simulateurs actifs
xcrun simctl list devices booted
Appareil iOS physique : complexité et sécurité
Tester sur un iPhone ou iPad physique nécessite un compte Apple Developer et une procédure de signature d'applications plus complexe que sur Android. Cette complexité reflète la politique de sécurité stricte d'Apple.
Prérequis pour appareils iOS :
- Compte Apple Developer (payant, ~99$/an)
- Certificat de développement valide
- Provisioning Profile incluant l'UDID de l'appareil de test
- WebDriverAgent compilé et signé
Configuration de l'appareil iOS :
- Connecter l'iPhone/iPad au Mac via USB
- Faire confiance à l'ordinateur (popup sur l'appareil iOS)
- Dans Xcode, ajouter l'appareil : Window > Devices and Simulators
- Installer WebDriverAgent sur l'appareil via Xcode
- Valider l'application dans Réglages > Général > Gestion des appareils
Desired Capabilities : la configuration de vos sessions Appium
Les Desired Capabilities constituent le contrat entre votre script de test et le serveur Appium. Ces paramètres définissent précisément l'environnement d'exécution souhaité : plateforme cible, appareil à utiliser, application à tester, et nombreuses options de comportement.
Comprendre et maîtriser les capabilities est crucial car elles déterminent directement la réussite ou l'échec de vos sessions de test. Une capability mal configurée peut entraîner des échecs de connexion, des comportements imprévisibles, ou des performances dégradées.
Architecture et évolution des capabilities
Avec Appium 2.x, la spécification des capabilities a évolué pour se conformer au standard W3C WebDriver. Cette évolution introduit la notion de préfixes de namespace pour éviter les conflits et améliorer la compatibilité avec l'écosystème Selenium.
Les capabilities se divisent désormais en deux catégories :
- Standard capabilities : définies par W3C (platformName, browserName, etc.)
- Vendor-specific capabilities : spécifiques à Appium, préfixées par "appium:"
Capabilities essentielles pour Android
Cette section détaille les capabilities indispensables pour automatiser des applications Android, avec des exemples concrets et des explications sur l'impact de chaque paramètre.
Configuration de base Android
DesiredCapabilities caps = new DesiredCapabilities();
// ✅ Capabilities standard W3C
caps.setCapability("platformName", "Android");
// ✅ Capabilities spécifiques Appium (préfixe appium:)
caps.setCapability("appium:deviceName", "Pixel_4_API_33");
caps.setCapability("appium:automationName", "UiAutomator2");
caps.setCapability("appium:app", "/path/to/your/app.apk");
// ✅ Pour applications déjà installées
caps.setCapability("appium:appPackage", "com.example.app");
caps.setCapability("appium:appActivity", "com.example.app.MainActivity");
Explications détaillées :
- platformName : Indique la plateforme cible (Android, iOS, Windows)
- appium:deviceName : Nom de l'appareil ou émulateur à utiliser
- appium:automationName : Moteur d'automatisation (UiAutomator2 recommandé)
- appium:app : Chemin vers l'APK à installer et tester
- appium:appPackage : Package de l'application (alternative à app)
- appium:appActivity : Activité principale à lancer
Capabilities avancées Android
// ✅ Gestion des permissions
caps.setCapability("appium:autoGrantPermissions", true);
// ✅ Reset de l'application
caps.setCapability("appium:noReset", false); // Reset app data
caps.setCapability("appium:fullReset", false); // Réinstallation complète
// ✅ Performance et stabilité
caps.setCapability("appium:newCommandTimeout", 300); // 5 minutes timeout
caps.setCapability("appium:androidInstallTimeout", 90000); // Installation timeout
// ✅ Configuration système
caps.setCapability("appium:autoAcceptAlerts", true);
caps.setCapability("appium:autoDismissAlerts", false);
// ✅ Options de debugging
caps.setCapability("appium:enablePerformanceLogging", true);
caps.setCapability("appium:printPageSourceOnFindFailure", true);
Capabilities pour iOS
Les capabilities iOS présentent des spécificités liées à l'écosystème Apple et aux contraintes de sécurité. La configuration diffère selon que vous ciblez un simulateur ou un appareil physique.
Configuration iOS Simulateur
DesiredCapabilities caps = new DesiredCapabilities();
// ✅ Configuration de base iOS
caps.setCapability("platformName", "iOS");
caps.setCapability("appium:deviceName", "iPhone 14 Pro");
caps.setCapability("appium:platformVersion", "16.0");
caps.setCapability("appium:automationName", "XCUITest");
// ✅ Application à tester
caps.setCapability("appium:app", "/path/to/your/app.app");
// OU pour une app installée
caps.setCapability("appium:bundleId", "com.example.iosapp");
// ✅ Simulateur spécifique
caps.setCapability("appium:udid", "auto"); // Auto-détection
Configuration iOS Appareil physique
// ✅ Appareil physique iOS
caps.setCapability("appium:udid", "00008030-001C2D223A02802E"); // UDID réel
caps.setCapability("appium:xcodeOrgId", "TEAM_ID_FROM_APPLE");
caps.setCapability("appium:xcodeSigningId", "iPhone Developer");
// ✅ WebDriverAgent sur appareil physique
caps.setCapability("appium:useNewWDA", true);
caps.setCapability("appium:wdaLaunchTimeout", 60000);
Patterns de configuration avancés
Pour les projets complexes, il est recommandé d'externaliser les capabilities dans des fichiers de configuration séparés, permettant une gestion plus flexible des environnements de test.
Configuration externalisée JSON
Créer un fichier capabilities.json pour chaque environnement :
{
"android": {
"platformName": "Android",
"appium:deviceName": "Pixel_4_API_33",
"appium:automationName": "UiAutomator2",
"appium:app": "./apps/android/demo.apk",
"appium:autoGrantPermissions": true,
"appium:noReset": false,
"appium:newCommandTimeout": 300
},
"ios": {
"platformName": "iOS",
"appium:deviceName": "iPhone 14 Pro",
"appium:platformVersion": "16.0",
"appium:automationName": "XCUITest",
"appium:app": "./apps/ios/demo.app",
"appium:udid": "auto"
}
}
Chargement dynamique des capabilities
public class CapabilitiesLoader {
public static DesiredCapabilities loadCapabilities(String platform) throws IOException {
// Charger le fichier JSON
String jsonPath = "src/test/resources/capabilities.json";
String content = Files.readString(Paths.get(jsonPath));
// Parser le JSON
JSONObject json = new JSONObject(content);
JSONObject platformCaps = json.getJSONObject(platform);
// Convertir en DesiredCapabilities
DesiredCapabilities caps = new DesiredCapabilities();
for (String key : platformCaps.keySet()) {
caps.setCapability(key, platformCaps.get(key));
}
return caps;
}
}
Projet Java avec Maven : architecture et bonnes pratiques
Maven transcende son rôle de simple gestionnaire de dépendances pour devenir l'épine dorsale de votre projet de test Appium. Il standardise la structure du projet, automatise les tâches de build, orchestre l'exécution des tests, et facilite l'intégration dans les pipelines CI/CD.
Création d'un projet Maven optimisé
Plutôt que de créer un projet Maven générique, nous allons structurer un projet spécifiquement optimisé pour les tests Appium avec toutes les bonnes pratiques intégrées dès le départ.
Génération du squelette de projet
# Création du projet Maven avec archetype personnalisé
mvn archetype:generate \
-DgroupId=com.company.mobile.tests \
-DartifactId=appium-test-suite \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
# Navigation dans le projet
cd appium-test-suite
Structure de projet recommandée
appium-test-suite/
├── pom.xml # Configuration Maven
├── src/
│ ├── main/
│ │ └── java/
│ │ └── com/company/mobile/
│ │ ├── pages/ # Page Object Models
│ │ │ ├── BasePage.java
│ │ │ ├── LoginPage.java
│ │ │ └── HomePage.java
│ │ ├── utils/ # Utilitaires et helpers
│ │ │ ├── DriverManager.java
│ │ │ ├── ConfigLoader.java
│ │ │ └── ScreenshotUtils.java
│ │ └── config/ # Configurations
│ │ └── AppiumConfig.java
│ └── test/
│ ├── java/
│ │ └── com/company/mobile/
│ │ ├── tests/ # Classes de test
│ │ │ ├── BaseTest.java
│ │ │ ├── LoginTests.java
│ │ │ └── NavigationTests.java
│ │ └── runners/ # Test runners
│ │ └── TestRunner.java
│ └── resources/
│ ├── capabilities/ # Fichiers de configuration
│ │ ├── android.json
│ │ └── ios.json
│ ├── test-data/ # Données de test
│ │ └── users.json
│ └── apps/ # Applications à tester
│ ├── android/
│ │ └── demo.apk
│ └── ios/
│ └── demo.app
Configuration pom.xml moderne et complète
Le fichier pom.xml suivant intègre toutes les dépendances nécessaires avec les versions les plus récentes et les meilleures pratiques de configuration :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.mobile</groupId>
<artifactId>appium-test-suite</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Appium Mobile Test Suite</name>
<description>Suite de tests automatisés pour applications mobiles</description>
<properties>
<!-- Versions Java -->
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Versions des dépendances principales -->
<appium.version>9.3.0</appium.version>
<selenium.version>4.25.0</selenium.version>
<testng.version>7.10.2</testng.version>
<allure.version>2.24.0</allure.version>
<!-- Versions des utilitaires -->
<jackson.version>2.15.2</jackson.version>
<slf4j.version>2.0.9</slf4j.version>
<commons-io.version>2.13.0</commons-io.version>
</properties>
<dependencies>
<!-- ✅ Appium Java Client - Version moderne -->
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>${appium.version}</version>
</dependency>
<!-- ✅ Selenium WebDriver - Compatible Appium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
<!-- ✅ TestNG - Framework de tests -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>
<!-- ✅ Allure - Reporting avancé -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>${allure.version}</version>
</dependency>
<!-- ✅ Jackson - Parsing JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- ✅ Apache Commons IO - Utilitaires fichiers -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<!-- ✅ SLF4J - Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- ✅ Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- ✅ Surefire Plugin - Exécution des tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.20/aspectjweaver-1.9.20.jar"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.20</version>
</dependency>
</dependencies>
</plugin>
<!-- ✅ Allure Plugin - Génération de rapports -->
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>2.12.0</version>
</plugin>
</plugins>
</build>
<!-- ✅ Profils pour différents environnements -->
<profiles>
<profile>
<id>android</id>
<properties>
<test.platform>android</test.platform>
</properties>
</profile>
<profile>
<id>ios</id>
<properties>
<test.platform>ios</test.platform>
</properties>
</profile>
</profiles>
</project>
- Java 17 : Version LTS moderne recommandée
- Appium 9.3.0 : Version récente sans MobileElement
- Selenium 4.25.0 : Compatible avec Appium moderne
- TestNG + Allure : Framework de test avec reporting avancé
- Profils Maven : Séparation Android/iOS
- Plugins optimisés : Surefire configuré pour TestNG et Allure
Configuration TestNG
Créez le fichier src/test/resources/testng.xml pour orchestrer vos tests :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Appium Mobile Test Suite" verbose="1" parallel="tests" thread-count="2">
<!-- Configuration globale -->
<parameter name="appium.server.url" value="http://127.0.0.1:4723"/>
<parameter name="implicit.wait" value="10"/>
<parameter name="explicit.wait" value="15"/>
<!-- Listeners pour le reporting -->
<listeners>
<listener class-name="io.qameta.allure.testng.AllureTestNg"/>
</listeners>
<!-- Suite de tests Android -->
<test name="Android Tests" preserve-order="true">
<parameter name="test.platform" value="android"/>
<classes>
<class name="com.company.mobile.tests.LoginTests"/>
<class name="com.company.mobile.tests.NavigationTests"/>
</classes>
</test>
</suite>
Exécution avec Maven
Voici les commandes Maven essentielles pour l'exécution de vos tests :
# Exécution de base
mvn clean test
# Avec profil Android
mvn clean test -Pandroid
# Avec profil iOS
mvn clean test -Pios
# Exécuter une classe spécifique
mvn test -Dtest=LoginTests
# Exécuter avec génération de rapport Allure
mvn clean test allure:report
# Servir le rapport Allure localement
mvn allure:serve
Optimisation des performances
Pour optimiser l'exécution de vos tests Appium :
# Configuration JVM optimisée
MAVEN_OPTS="-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC" mvn clean test
# Tests parallèles (attention : besoin de plusieurs émulateurs)
mvn test -DthreadCount=2 -Dparallel=classes
# Mode debug avec logs détaillés
mvn test -X -Dappium.log.level=debug
- Gérer les dépendances Appium modernes automatiquement
- Structurer votre projet de manière professionnelle
- Exécuter vos tests de façon flexible (Android/iOS)
- Générer des rapports visuels avec Allure
- Intégrer facilement dans un pipeline CI/CD
Exemple de test Spock avec code moderne
Spock est un framework de test puissant pour Java et Groovy qui offre une syntaxe expressive et des fonctionnalités avancées comme les tests paramétrés et les mocks intégrés. Voici comment l'utiliser avec Appium et du code moderne.
Configuration Spock dans le pom.xml
Ajoutez ces dépendances à votre pom.xml pour utiliser Spock avec Appium :
<!-- ✅ Spock Framework -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>2.3-groovy-4.0</version>
<scope>test</scope>
</dependency>
<!-- ✅ Groovy (requis par Spock) -->
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>4.0.15</version>
<type>pom</type>
<scope>test</scope>
</dependency>
<!-- Plugin Groovy pour Maven -->
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<goals>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
</plugin>
Classe de test Spock moderne
Créez le fichier src/test/groovy/com/company/mobile/tests/LoginSpec.groovy :
package com.company.mobile.tests
import io.appium.java_client.AppiumBy
import io.appium.java_client.android.AndroidDriver
import org.openqa.selenium.WebElement
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.support.ui.WebDriverWait
import org.openqa.selenium.support.ui.ExpectedConditions
import spock.lang.*
import java.time.Duration
class LoginSpec extends Specification {
// ✅ Driver moderne sans paramètre générique
static AndroidDriver driver
static WebDriverWait wait
def setupSpec() {
// ✅ Configuration avec capabilities modernes
def caps = new DesiredCapabilities()
caps.setCapability("platformName", "Android")
caps.setCapability("appium:deviceName", "Android Emulator")
caps.setCapability("appium:automationName", "UiAutomator2")
caps.setCapability("appium:app", getAppPath())
caps.setCapability("appium:autoGrantPermissions", true)
caps.setCapability("appium:noReset", false)
caps.setCapability("appium:newCommandTimeout", 300)
// ✅ URL moderne sans /wd/hub
driver = new AndroidDriver(new URL("http://127.0.0.1:4723"), caps)
// ✅ Configuration des timeouts
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10))
wait = new WebDriverWait(driver, Duration.ofSeconds(15))
}
def cleanupSpec() {
if (driver != null) {
driver.quit()
}
}
def "utilisateur peut naviguer vers la section App"() {
when: "je clique sur la section App"
WebElement appSection = driver.findElement(
AppiumBy.androidUIAutomator('new UiSelector().text("App")')
)
appSection.click()
then: "la section App doit être accessible"
WebElement activitySection = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator('new UiSelector().text("Activity")')
)
)
activitySection.isDisplayed()
}
def "formulaire de saisie fonctionne correctement"() {
given: "je navigue vers une page avec des champs de saisie"
driver.findElement(AppiumBy.androidUIAutomator('new UiSelector().text("Views")')).click()
WebElement controlsOption = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator(
'new UiScrollable(new UiSelector().scrollable(true))' +
'.scrollIntoView(new UiSelector().text("Controls"))'
)
)
)
controlsOption.click()
driver.findElement(
AppiumBy.androidUIAutomator('new UiSelector().text("1. Light Theme")')
).click()
when: "je saisis du texte dans le champ"
WebElement editText = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.className("android.widget.EditText")
)
)
String testText = "Test Spock avec Appium moderne!"
editText.clear()
editText.sendKeys(testText)
then: "le texte doit être correctement saisi"
editText.getText() == testText
and: "je peux fermer le clavier"
try {
driver.hideKeyboard()
} catch (Exception e) {
// Clavier déjà fermé
}
true // Test réussi
}
def "checkbox et radiobutton fonctionnent avec différentes valeurs"() {
given: "je suis sur la page des contrôles"
navigateToControlsPage()
when: "je teste différents états de checkbox"
WebElement checkbox = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/check1")
)
def initialState = checkbox.isSelected()
checkbox.click()
def newState = checkbox.isSelected()
then: "l'état de la checkbox doit changer"
initialState != newState
when: "je teste les radio buttons"
WebElement radio1 = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/radio1")
)
WebElement radio2 = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/radio2")
)
radio1.click()
def radio1Selected = radio1.isSelected()
radio2.click()
def radio2Selected = radio2.isSelected()
def radio1AfterRadio2 = radio1.isSelected()
then: "seul un radio button doit être sélectionné à la fois"
radio1Selected == true
radio2Selected == true
radio1AfterRadio2 == false
}
@Unroll
def "test paramétré avec différentes données: #testData"() {
given: "je navigue vers la page de saisie"
navigateToTextInputPage()
when: "je saisis les données de test"
WebElement editText = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.className("android.widget.EditText")
)
)
editText.clear()
editText.sendKeys(testData)
then: "le texte doit être correctement affiché"
editText.getText() == testData
where: "les données de test sont"
testData << [
"Test simple",
"Test avec des chiffres 123",
"Test avec caractères spéciaux !@#",
"Test très long pour vérifier la capacité du champ de texte à gérer du contenu étendu"
]
}
def "gestion d'erreurs avec timeout"() {
when: "je cherche un élément qui n'existe pas"
try {
wait.until(
ExpectedConditions.visibilityOfElementLocated(
AppiumBy.id("element.inexistant")
)
)
} catch (Exception e) {
// Exception attendue
}
then: "le test ne doit pas planter"
driver != null
driver.getPageSource() != null
}
// ✅ Méthodes utilitaires privées
private void navigateToControlsPage() {
driver.findElement(AppiumBy.androidUIAutomator('new UiSelector().text("Views")')).click()
WebElement controlsOption = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator(
'new UiScrollable(new UiSelector().scrollable(true))' +
'.scrollIntoView(new UiSelector().text("Controls"))'
)
)
)
controlsOption.click()
driver.findElement(
AppiumBy.androidUIAutomator('new UiSelector().text("1. Light Theme")')
).click()
}
private void navigateToTextInputPage() {
navigateToControlsPage()
}
private String getAppPath() {
return System.getProperty("user.dir") + "/src/test/resources/apps/android/ApiDemos-debug.apk"
}
}
Exécution des tests Spock
Les tests Spock s'exécutent comme des tests classiques avec Maven :
# Exécuter tous les tests (y compris Spock)
mvn clean test
# Exécuter seulement les tests Spock
mvn test -Dtest="*Spec"
# Exécuter un test Spock spécifique
mvn test -Dtest="LoginSpec"
- Syntaxe expressive : given/when/then plus lisible
- Tests paramétrés : @Unroll pour tester plusieurs datasets
- Mocks intégrés : pas besoin de Mockito
- Assertions puissantes : conditions multiples avec and/or
- Groovy : syntaxe plus concise que Java
Exécution avancée avec Maven
Maven offre une flexibilité exceptionnelle pour l'exécution de tests Appium. Cette section détaille les commandes avancées, les profils de configuration, et les techniques d'optimisation pour différents scénarios d'exécution.
Commandes de base
Ces commandes constituent le socle de l'exécution quotidienne des tests :
# ✅ Compilation et exécution complète
mvn clean compile test
# ✅ Exécution rapide sans nettoyage
mvn test
# ✅ Ignorer les échecs de tests (pour CI/CD)
mvn test -Dmaven.test.failure.ignore=true
# ✅ Exécution en mode offline (sans téléchargement)
mvn test -o
Exécution sélective
Pour des cycles de développement plus rapides, l'exécution sélective est essentielle :
# ✅ Exécuter une classe de test spécifique
mvn test -Dtest=LoginTests
# ✅ Exécuter une méthode de test spécifique
mvn test -Dtest=LoginTests#testValidLogin
# ✅ Exécuter plusieurs classes
mvn test -Dtest=LoginTests,NavigationTests,CheckoutTests
# ✅ Exécuter par pattern de nom
mvn test -Dtest="*Login*"
# ✅ Exécuter par package
mvn test -Dtest="com.company.mobile.tests.smoke.*"
# ✅ Exclure certains tests
mvn test -Dtest="!*Integration*"
Configuration d'environnement
Adapter l'exécution selon l'environnement cible :
# ✅ Spécifier la plateforme de test
mvn test -Dtest.platform=android
mvn test -Dtest.platform=ios
# ✅ Configurer le serveur Appium
mvn test -Dappium.server.url=http://192.168.1.100:4723
# ✅ Ajuster les timeouts
mvn test -Dimplicit.wait=15 -Dexplicit.wait=30
# ✅ Spécifier l'application à tester
mvn test -Dapp.path=/path/to/your/app.apk
# ✅ Configurer le device
mvn test -Ddevice.name="Pixel_6_API_33"
Profils Maven avancés
Définissez des profils complexes dans votre pom.xml pour différents environnements :
<profiles>
<!-- ✅ Profil de développement local -->
<profile>
<id>dev</id>
<properties>
<test.platform>android</test.platform>
<appium.server.url>http://127.0.0.1:4723</appium.server.url>
<device.name>Android Emulator</device.name>
<implicit.wait>10</implicit.wait>
</properties>
</profile>
<!-- ✅ Profil d'intégration continue -->
<profile>
<id>ci</id>
<properties>
<test.platform>android</test.platform>
<appium.server.url>http://appium-grid:4723</appium.server.url>
<device.name>ci-emulator</device.name>
<implicit.wait>15</implicit.wait>
<maven.test.failure.ignore>false</maven.test.failure.ignore>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<reportsDirectory>${project.build.directory}/ci-reports</reportsDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- ✅ Profil de tests de performance -->
<profile>
<id>performance</id>
<properties>
<test.platform>android</test.platform>
<parallel.tests>true</parallel.tests>
<thread.count>3</thread.count>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>classes</parallel>
<threadCount>${thread.count}</threadCount>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Exécution avec profils
# ✅ Utiliser le profil de développement
mvn clean test -Pdev
# ✅ Utiliser le profil CI
mvn clean test -Pci
# ✅ Combiner plusieurs profils
mvn clean test -Pci,performance
# ✅ Surcharger des propriétés de profil
mvn test -Pdev -Ddevice.name="Pixel_7_API_34"
Optimisation des performances
Techniques pour accélérer l'exécution des tests :
# ✅ Configuration JVM optimisée
export MAVEN_OPTS="-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+UseZGC"
# ✅ Exécution parallèle par classes (attention aux resources)
mvn test -Dparallel=classes -DthreadCount=2
# ✅ Exécution parallèle par méthodes
mvn test -Dparallel=methods -DthreadCount=4
# ✅ Compilation incrémentale
mvn test -Dmaven.compiler.useIncrementalCompilation=true
# ✅ Skip des étapes non nécessaires
mvn test -DskipTests=false -Dmaven.javadoc.skip=true -Dmaven.source.skip=true
Intégration avec Allure Reports
Génération automatique de rapports visuels :
# ✅ Exécuter les tests avec génération des données Allure
mvn clean test
# ✅ Générer le rapport HTML
mvn allure:report
# ✅ Ouvrir le rapport dans le navigateur
mvn allure:serve
# ✅ Pipeline complet
mvn clean test allure:report allure:serve
# ✅ Générer le rapport avec historique
mvn allure:report -Dallure.results.directory=target/allure-results
Debugging et logs avancés
# ✅ Mode debug Maven complet
mvn test -X -Dappium.log.level=debug
# ✅ Logs détaillés sans le mode debug
mvn test -Dorg.slf4j.simpleLogger.defaultLogLevel=debug
# ✅ Capturer la sortie dans un fichier
mvn test -l test-execution.log
# ✅ Afficher les propriétés système utilisées
mvn test -Dtest=LoginTests -X | grep -E "test\.|appium\.|device\."
Scripts d'automatisation
Créez des scripts pour standardiser l'exécution :
Script bash pour Linux/Mac (run-tests.sh)
#!/bin/bash
# Configuration par défaut
PLATFORM="android"
PROFILE="dev"
TEST_CLASS=""
# Gestion des arguments
while [[ $# -gt 0 ]]; do
case $1 in
-p|--platform)
PLATFORM="$2"
shift 2
;;
--profile)
PROFILE="$2"
shift 2
;;
-t|--test)
TEST_CLASS="$2"
shift 2
;;
*)
echo "Option inconnue: $1"
exit 1
;;
esac
done
echo "🚀 Lancement des tests Appium"
echo "Plateforme: $PLATFORM"
echo "Profil: $PROFILE"
echo "Classe de test: ${TEST_CLASS:-'Toutes'}"
# Construction de la commande Maven
MVN_CMD="mvn clean test -P$PROFILE -Dtest.platform=$PLATFORM"
if [ ! -z "$TEST_CLASS" ]; then
MVN_CMD="$MVN_CMD -Dtest=$TEST_CLASS"
fi
echo "Commande: $MVN_CMD"
echo ""
# Exécution
$MVN_CMD
# Génération du rapport si les tests sont passés
if [ $? -eq 0 ]; then
echo "✅ Tests réussis - Génération du rapport Allure"
mvn allure:report allure:serve
else
echo "❌ Échec des tests"
exit 1
fi
Utilisation du script
# ✅ Rendre le script exécutable
chmod +x run-tests.sh
# ✅ Exécuter avec paramètres
./run-tests.sh --platform android --profile dev --test LoginTests
# ✅ Exécuter avec configuration par défaut
./run-tests.sh
- Adapter l'exécution selon l'environnement (dev, CI, production)
- Optimiser les performances avec l'exécution parallèle
- Générer des rapports automatiquement avec Allure
- Automatiser avec des scripts personnalisés
- Débugger efficacement avec des logs détaillés
source ~/.bashrc ou équivalent.
Émulateurs & Appareils physiques : choisir la bonne stratégie de test
Le choix entre émulateurs et appareils physiques constitue l'une des décisions stratégiques majeures dans la mise en place de tests Appium. Chaque approche présente des avantages et inconvénients qu'il convient de comprendre pour optimiser votre stratégie de test.
Émulateurs Android : la puissance de la virtualisation
Les émulateurs Android (AVD - Android Virtual Device) sont des machines virtuelles qui simulent un appareil Android complet sur votre ordinateur. Cette approche offre une flexibilité exceptionnelle pour les tests automatisés, particulièrement dans les environnements de développement et d'intégration continue.
Avantages des émulateurs :
- Reproductibilité : configuration identique entre tous les environnements de test
- Économie : pas d'investissement en hardware physique
- Parallélisation : possibilité de lancer plusieurs instances simultanément
- Contrôle complet : simulation de conditions réseau, batterie, localisation GPS
- Intégration CI/CD : parfait pour l'automatisation complète
- Reset facile : retour à un état propre en quelques secondes
Inconvénients des émulateurs :
- Performance : généralement plus lents que les appareils physiques
- Fidélité limitée : certains comportements hardware non simulés
- Consommation ressources : utilisation intensive CPU/RAM de la machine hôte
- Limitations capteurs : caméra, NFC, certains capteurs indisponibles
Création d'un émulateur Android optimisé :
La création d'un émulateur efficace nécessite un équilibre entre performance et fidélité. Voici la procédure détaillée pour créer un AVD optimisé pour les tests Appium :
- Ouvrir Android Studio et naviguer vers Tools > Device Manager
- Cliquer sur "Create Device" pour lancer l'assistant de création
- Sélection du hardware :
- Privilégier les profils Pixel (Pixel 4, Pixel 6, Pixel 7) pour leur compatibilité optimale
- Éviter les profils avec trop de RAM (>4GB) qui ralentissent la machine hôte
- Pour les tablettes, Pixel C ou Nexus 10 sont de bons compromis
- Sélection de l'image système :
- API Level 30 (Android 11) ou API 33 (Android 13) pour la modernité
- Target x86_64 pour les meilleures performances sur PC Intel/AMD
- Google APIs si vous testez des apps utilisant les services Google
- Éviter les images ARM sur machine x86 (très lent par émulation)
- Configuration avancée :
- RAM : 2048-4096 MB (équilibre performance/ressources)
- Storage interne : 8GB minimum, 16GB recommandé
- Graphics : Hardware GLES 2.0 si supporté, Software sinon
- Boot option : Cold boot (plus stable pour les tests)
Validation de l'émulateur :
# Lancer l'émulateur depuis la ligne de commande
emulator -avd Pixel_4_API_33
# Dans un autre terminal, vérifier la détection
adb devices
# Sortie attendue : emulator-5554 device
# Vérifier les capacités de l'émulateur
adb shell getprop ro.build.version.release
# Sortie attendue : 13 (pour Android 13)
Appareil Android physique : fidélité maximale
Tester sur un appareil Android physique reste indispensable pour valider le comportement réel de votre application. Les différences entre émulation et réalité peuvent être subtiles mais critiques : performances réelles, comportements des capteurs, interactions avec le système, gestion des notifications, etc.
Activation du mode développeur :
Cette procédure est identique sur la plupart des appareils Android, mais peut varier légèrement selon les constructeurs :
- Ouvrir Paramètres > À propos du téléphone (ou "À propos de l'appareil")
- Rechercher "Numéro de build" ou "Version du logiciel"
- Taper 7 fois rapidement sur cette entrée
- Un message confirme l'activation : "Vous êtes maintenant un développeur"
- Retourner dans Paramètres : un nouveau menu "Options pour les développeurs" apparaît
Configuration du débogage USB :
- Dans "Options pour les développeurs", activer "Débogage USB"
- Optionnel mais recommandé : activer "Rester éveillé" (évite la veille pendant les tests)
- Connecter l'appareil via USB à l'ordinateur
- Une popup apparaît sur l'appareil : "Autoriser le débogage USB ?"
- Cocher "Toujours autoriser depuis cet ordinateur" et valider
Résolution des problèmes de connexion :
La connexion d'appareils physiques peut poser des défis spécifiques selon l'OS et le constructeur :
Sur Windows :
- Installer les pilotes USB spécifiques au constructeur (Samsung, Xiaomi, OnePlus, etc.)
- Les pilotes "universels" de Windows ne suffisent généralement pas
- En cas d'échec, utiliser les pilotes génériques Google USB depuis Android Studio
Sur macOS :
- Généralement plug-and-play, pas de pilotes supplémentaires nécessaires
- En cas de problème, vérifier les autorisations de sécurité macOS
Sur Linux :
- Configurer les règles udev pour les permissions USB
- Ajouter l'utilisateur au groupe "plugdev"
- Redémarrer le service udev :
sudo service udev restart
Validation de la connexion :
# Vérifier la détection de l'appareil
adb devices
# Sortie attendue : R58M12345X device (pas unauthorized)
# Tester la communication
adb shell echo "Test de connexion"
# Doit retourner : Test de connexion
# Vérifier les informations système
adb shell getprop ro.product.model
# Retourne le modèle de l'appareil
Configuration iOS : écosystème Apple
L'automatisation iOS avec Appium nécessite un environnement macOS et présente des défis spécifiques liés aux politiques de sécurité d'Apple. Cette section détaille les prérequis et procédures pour iOS.
Simulateur iOS : l'émulation officielle Apple
Contrairement à Android où les émulateurs sont des machines virtuelles complètes, les simulateurs iOS sont des environnements d'exécution natifs qui simulent l'interface utilisateur d'iOS sur macOS. Cette approche offre d'excellentes performances mais avec certaines limitations fonctionnelles.
Installation et configuration Xcode :
- Installer Xcode depuis l'App Store (installation longue, ~10GB)
- Lancer Xcode une première fois pour finaliser l'installation
- Accepter les termes de licence :
sudo xcodebuild -license accept - Ouvrir Xcode > Preferences > Platforms
- Télécharger les simulateurs iOS souhaités (iOS 15, 16, 17)
Gestion des simulateurs iOS :
# Lister tous les simulateurs disponibles
xcrun simctl list devices
# Créer un nouveau simulateur personnalisé
xcrun simctl create "iPhone14-Test" "iPhone 14" "iOS16.0"
# Lancer un simulateur spécifique
xcrun simctl boot "iPhone 14"
open -a Simulator
# Vérifier les simulateurs actifs
xcrun simctl list devices booted
Appareil iOS physique : complexité et sécurité
Tester sur un iPhone ou iPad physique nécessite un compte Apple Developer et une procédure de signature d'applications plus complexe que sur Android. Cette complexité reflète la politique de sécurité stricte d'Apple.
Prérequis pour appareils iOS :
- Compte Apple Developer (payant, ~99$/an)
- Certificat de développement valide
- Provisioning Profile incluant l'UDID de l'appareil de test
- WebDriverAgent compilé et signé
Configuration de l'appareil iOS :
- Connecter l'iPhone/iPad au Mac via USB
- Faire confiance à l'ordinateur (popup sur l'appareil iOS)
- Dans Xcode, ajouter l'appareil : Window > Devices and Simulators
- Installer WebDriverAgent sur l'appareil via Xcode
- Valider l'application dans Réglages > Général > Gestion des appareils
Desired Capabilities : la configuration de vos sessions Appium
Les Desired Capabilities constituent le contrat entre votre script de test et le serveur Appium. Ces paramètres définissent précisément l'environnement d'exécution souhaité : plateforme cible, appareil à utiliser, application à tester, et nombreuses options de comportement.
Comprendre et maîtriser les capabilities est crucial car elles déterminent directement la réussite ou l'échec de vos sessions de test. Une capability mal configurée peut entraîner des échecs de connexion, des comportements imprévisibles, ou des performances dégradées.
Architecture et évolution des capabilities
Avec Appium 2.x, la spécification des capabilities a évolué pour se conformer au standard W3C WebDriver. Cette évolution introduit la notion de préfixes de namespace pour éviter les conflits et améliorer la compatibilité avec l'écosystème Selenium.
Les capabilities se divisent désormais en deux catégories :
- Standard capabilities : définies par W3C (platformName, browserName, etc.)
- Vendor-specific capabilities : spécifiques à Appium, préfixées par "appium:"
Capabilities essentielles pour Android
Cette section détaille les capabilities indispensables pour automatiser des applications Android, avec des exemples concrets et des explications sur l'impact de chaque paramètre.
Configuration de base Android
DesiredCapabilities caps = new DesiredCapabilities();
// ✅ Capabilities standard W3C
caps.setCapability("platformName", "Android");
// ✅ Capabilities spécifiques Appium (préfixe appium:)
caps.setCapability("appium:deviceName", "Pixel_4_API_33");
caps.setCapability("appium:automationName", "UiAutomator2");
caps.setCapability("appium:app", "/path/to/your/app.apk");
// ✅ Pour applications déjà installées
caps.setCapability("appium:appPackage", "com.example.app");
caps.setCapability("appium:appActivity", "com.example.app.MainActivity");
Explications détaillées :
- platformName : Indique la plateforme cible (Android, iOS, Windows)
- appium:deviceName : Nom de l'appareil ou émulateur à utiliser
- appium:automationName : Moteur d'automatisation (UiAutomator2 recommandé)
- appium:app : Chemin vers l'APK à installer et tester
- appium:appPackage : Package de l'application (alternative à app)
- appium:appActivity : Activité principale à lancer
Capabilities avancées Android
// ✅ Gestion des permissions
caps.setCapability("appium:autoGrantPermissions", true);
// ✅ Reset de l'application
caps.setCapability("appium:noReset", false); // Reset app data
caps.setCapability("appium:fullReset", false); // Réinstallation complète
// ✅ Performance et stabilité
caps.setCapability("appium:newCommandTimeout", 300); // 5 minutes timeout
caps.setCapability("appium:androidInstallTimeout", 90000); // Installation timeout
// ✅ Configuration système
caps.setCapability("appium:autoAcceptAlerts", true);
caps.setCapability("appium:autoDismissAlerts", false);
// ✅ Options de debugging
caps.setCapability("appium:enablePerformanceLogging", true);
caps.setCapability("appium:printPageSourceOnFindFailure", true);
Capabilities pour iOS
Les capabilities iOS présentent des spécificités liées à l'écosystème Apple et aux contraintes de sécurité. La configuration diffère selon que vous ciblez un simulateur ou un appareil physique.
Configuration iOS Simulateur
DesiredCapabilities caps = new DesiredCapabilities();
// ✅ Configuration de base iOS
caps.setCapability("platformName", "iOS");
caps.setCapability("appium:deviceName", "iPhone 14 Pro");
caps.setCapability("appium:platformVersion", "16.0");
caps.setCapability("appium:automationName", "XCUITest");
// ✅ Application à tester
caps.setCapability("appium:app", "/path/to/your/app.app");
// OU pour une app installée
caps.setCapability("appium:bundleId", "com.example.iosapp");
// ✅ Simulateur spécifique
caps.setCapability("appium:udid", "auto"); // Auto-détection
Configuration iOS Appareil physique
// ✅ Appareil physique iOS
caps.setCapability("appium:udid", "00008030-001C2D223A02802E"); // UDID réel
caps.setCapability("appium:xcodeOrgId", "TEAM_ID_FROM_APPLE");
caps.setCapability("appium:xcodeSigningId", "iPhone Developer");
// ✅ WebDriverAgent sur appareil physique
caps.setCapability("appium:useNewWDA", true);
caps.setCapability("appium:wdaLaunchTimeout", 60000);
Patterns de configuration avancés
Pour les projets complexes, il est recommandé d'externaliser les capabilities dans des fichiers de configuration séparés, permettant une gestion plus flexible des environnements de test.
Configuration externalisée JSON
Créer un fichier capabilities.json pour chaque environnement :
{
"android": {
"platformName": "Android",
"appium:deviceName": "Pixel_4_API_33",
"appium:automationName": "UiAutomator2",
"appium:app": "./apps/android/demo.apk",
"appium:autoGrantPermissions": true,
"appium:noReset": false,
"appium:newCommandTimeout": 300
},
"ios": {
"platformName": "iOS",
"appium:deviceName": "iPhone 14 Pro",
"appium:platformVersion": "16.0",
"appium:automationName": "XCUITest",
"appium:app": "./apps/ios/demo.app",
"appium:udid": "auto"
}
}
Chargement dynamique des capabilities
public class CapabilitiesLoader {
public static DesiredCapabilities loadCapabilities(String platform) throws IOException {
// Charger le fichier JSON
String jsonPath = "src/test/resources/capabilities.json";
String content = Files.readString(Paths.get(jsonPath));
// Parser le JSON
JSONObject json = new JSONObject(content);
JSONObject platformCaps = json.getJSONObject(platform);
// Convertir en DesiredCapabilities
DesiredCapabilities caps = new DesiredCapabilities();
for (String key : platformCaps.keySet()) {
caps.setCapability(key, platformCaps.get(key));
}
return caps;
}
}
Projet Java avec Maven : architecture et bonnes pratiques
Maven transcende son rôle de simple gestionnaire de dépendances pour devenir l'épine dorsale de votre projet de test Appium. Il standardise la structure du projet, automatise les tâches de build, orchestre l'exécution des tests, et facilite l'intégration dans les pipelines CI/CD.
Création d'un projet Maven optimisé
Plutôt que de créer un projet Maven générique, nous allons structurer un projet spécifiquement optimisé pour les tests Appium avec toutes les bonnes pratiques intégrées dès le départ.
Génération du squelette de projet
# Création du projet Maven avec archetype personnalisé
mvn archetype:generate \
-DgroupId=com.company.mobile.tests \
-DartifactId=appium-test-suite \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
# Navigation dans le projet
cd appium-test-suite
Structure de projet recommandée
appium-test-suite/
├── pom.xml # Configuration Maven
├── src/
│ ├── main/
│ │ └── java/
│ │ └── com/company/mobile/
│ │ ├── pages/ # Page Object Models
│ │ │ ├── BasePage.java
│ │ │ ├── LoginPage.java
│ │ │ └── HomePage.java
│ │ ├── utils/ # Utilitaires et helpers
│ │ │ ├── DriverManager.java
│ │ │ ├── ConfigLoader.java
│ │ │ └── ScreenshotUtils.java
│ │ └── config/ # Configurations
│ │ └── AppiumConfig.java
│ └── test/
│ ├── java/
│ │ └── com/company/mobile/
│ │ ├── tests/ # Classes de test
│ │ │ ├── BaseTest.java
│ │ │ ├── LoginTests.java
│ │ │ └── NavigationTests.java
│ │ └── runners/ # Test runners
│ │ └── TestRunner.java
│ └── resources/
│ ├── capabilities/ # Fichiers de configuration
│ │ ├── android.json
│ │ └── ios.json
│ ├── test-data/ # Données de test
│ │ └── users.json
│ └── apps/ # Applications à tester
│ ├── android/
│ │ └── demo.apk
│ └── ios/
│ └── demo.app
Configuration pom.xml moderne et complète
Le fichier pom.xml suivant intègre toutes les dépendances nécessaires avec les versions les plus récentes et les meilleures pratiques de configuration :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.mobile</groupId>
<artifactId>appium-test-suite</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Appium Mobile Test Suite</name>
<description>Suite de tests automatisés pour applications mobiles</description>
<properties>
<!-- Versions Java -->
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Versions des dépendances principales -->
<appium.version>9.3.0</appium.version>
<selenium.version>4.25.0</selenium.version>
<testng.version>7.10.2</testng.version>
<allure.version>2.24.0</allure.version>
<!-- Versions des utilitaires -->
<jackson.version>2.15.2</jackson.version>
<slf4j.version>2.0.9</slf4j.version>
<commons-io.version>2.13.0</commons-io.version>
</properties>
<dependencies>
<!-- ✅ Appium Java Client - Version moderne -->
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>${appium.version}</version>
</dependency>
<!-- ✅ Selenium WebDriver - Compatible Appium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
<!-- ✅ TestNG - Framework de tests -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>
<!-- ✅ Allure - Reporting avancé -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>${allure.version}</version>
</dependency>
<!-- ✅ Jackson - Parsing JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- ✅ Apache Commons IO - Utilitaires fichiers -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<!-- ✅ SLF4J - Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- ✅ Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- ✅ Surefire Plugin - Exécution des tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.20/aspectjweaver-1.9.20.jar"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.20</version>
</dependency>
</dependencies>
</plugin>
<!-- ✅ Allure Plugin - Génération de rapports -->
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>2.12.0</version>
</plugin>
</plugins>
</build>
<!-- ✅ Profils pour différents environnements -->
<profiles>
<profile>
<id>android</id>
<properties>
<test.platform>android</test.platform>
</properties>
</profile>
<profile>
<id>ios</id>
<properties>
<test.platform>ios</test.platform>
</properties>
</profile>
</profiles>
</project>
- Java 17 : Version LTS moderne recommandée
- Appium 9.3.0 : Version récente sans MobileElement
- Selenium 4.25.0 : Compatible avec Appium moderne
- TestNG + Allure : Framework de test avec reporting avancé
- Profils Maven : Séparation Android/iOS
- Plugins optimisés : Surefire configuré pour TestNG et Allure
Configuration TestNG
Créez le fichier src/test/resources/testng.xml pour orchestrer vos tests :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Appium Mobile Test Suite" verbose="1" parallel="tests" thread-count="2">
<!-- Configuration globale -->
<parameter name="appium.server.url" value="http://127.0.0.1:4723"/>
<parameter name="implicit.wait" value="10"/>
<parameter name="explicit.wait" value="15"/>
<!-- Listeners pour le reporting -->
<listeners>
<listener class-name="io.qameta.allure.testng.AllureTestNg"/>
</listeners>
<!-- Suite de tests Android -->
<test name="Android Tests" preserve-order="true">
<parameter name="test.platform" value="android"/>
<classes>
<class name="com.company.mobile.tests.LoginTests"/>
<class name="com.company.mobile.tests.NavigationTests"/>
</classes>
</test>
</suite>
Exécution avec Maven
Voici les commandes Maven essentielles pour l'exécution de vos tests :
# Exécution de base
mvn clean test
# Avec profil Android
mvn clean test -Pandroid
# Avec profil iOS
mvn clean test -Pios
# Exécuter une classe spécifique
mvn test -Dtest=LoginTests
# Exécuter avec génération de rapport Allure
mvn clean test allure:report
# Servir le rapport Allure localement
mvn allure:serve
Optimisation des performances
Pour optimiser l'exécution de vos tests Appium :
# Configuration JVM optimisée
MAVEN_OPTS="-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC" mvn clean test
# Tests parallèles (attention : besoin de plusieurs émulateurs)
mvn test -DthreadCount=2 -Dparallel=classes
# Mode debug avec logs détaillés
mvn test -X -Dappium.log.level=debug
- Gérer les dépendances Appium modernes automatiquement
- Structurer votre projet de manière professionnelle
- Exécuter vos tests de façon flexible (Android/iOS)
- Générer des rapports visuels avec Allure
- Intégrer facilement dans un pipeline CI/CD
Exemple de test Spock avec code moderne
Spock est un framework de test puissant pour Java et Groovy qui offre une syntaxe expressive et des fonctionnalités avancées comme les tests paramétrés et les mocks intégrés. Voici comment l'utiliser avec Appium et du code moderne.
Configuration Spock dans le pom.xml
Ajoutez ces dépendances à votre pom.xml pour utiliser Spock avec Appium :
<!-- ✅ Spock Framework -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>2.3-groovy-4.0</version>
<scope>test</scope>
</dependency>
<!-- ✅ Groovy (requis par Spock) -->
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>4.0.15</version>
<type>pom</type>
<scope>test</scope>
</dependency>
<!-- Plugin Groovy pour Maven -->
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<goals>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
</plugin>
Classe de test Spock moderne
Créez le fichier src/test/groovy/com/company/mobile/tests/LoginSpec.groovy :
package com.company.mobile.tests
import io.appium.java_client.AppiumBy
import io.appium.java_client.android.AndroidDriver
import org.openqa.selenium.WebElement
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.support.ui.WebDriverWait
import org.openqa.selenium.support.ui.ExpectedConditions
import spock.lang.*
import java.time.Duration
class LoginSpec extends Specification {
// ✅ Driver moderne sans paramètre générique
static AndroidDriver driver
static WebDriverWait wait
def setupSpec() {
// ✅ Configuration avec capabilities modernes
def caps = new DesiredCapabilities()
caps.setCapability("platformName", "Android")
caps.setCapability("appium:deviceName", "Android Emulator")
caps.setCapability("appium:automationName", "UiAutomator2")
caps.setCapability("appium:app", getAppPath())
caps.setCapability("appium:autoGrantPermissions", true)
caps.setCapability("appium:noReset", false)
caps.setCapability("appium:newCommandTimeout", 300)
// ✅ URL moderne sans /wd/hub
driver = new AndroidDriver(new URL("http://127.0.0.1:4723"), caps)
// ✅ Configuration des timeouts
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10))
wait = new WebDriverWait(driver, Duration.ofSeconds(15))
}
def cleanupSpec() {
if (driver != null) {
driver.quit()
}
}
def "utilisateur peut naviguer vers la section App"() {
when: "je clique sur la section App"
WebElement appSection = driver.findElement(
AppiumBy.androidUIAutomator('new UiSelector().text("App")')
)
appSection.click()
then: "la section App doit être accessible"
WebElement activitySection = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator('new UiSelector().text("Activity")')
)
)
activitySection.isDisplayed()
}
def "formulaire de saisie fonctionne correctement"() {
given: "je navigue vers une page avec des champs de saisie"
driver.findElement(AppiumBy.androidUIAutomator('new UiSelector().text("Views")')).click()
WebElement controlsOption = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator(
'new UiScrollable(new UiSelector().scrollable(true))' +
'.scrollIntoView(new UiSelector().text("Controls"))'
)
)
)
controlsOption.click()
driver.findElement(
AppiumBy.androidUIAutomator('new UiSelector().text("1. Light Theme")')
).click()
when: "je saisis du texte dans le champ"
WebElement editText = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.className("android.widget.EditText")
)
)
String testText = "Test Spock avec Appium moderne!"
editText.clear()
editText.sendKeys(testText)
then: "le texte doit être correctement saisi"
editText.getText() == testText
and: "je peux fermer le clavier"
try {
driver.hideKeyboard()
} catch (Exception e) {
// Clavier déjà fermé
}
true // Test réussi
}
def "checkbox et radiobutton fonctionnent avec différentes valeurs"() {
given: "je suis sur la page des contrôles"
navigateToControlsPage()
when: "je teste différents états de checkbox"
WebElement checkbox = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/check1")
)
def initialState = checkbox.isSelected()
checkbox.click()
def newState = checkbox.isSelected()
then: "l'état de la checkbox doit changer"
initialState != newState
when: "je teste les radio buttons"
WebElement radio1 = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/radio1")
)
WebElement radio2 = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/radio2")
)
radio1.click()
def radio1Selected = radio1.isSelected()
radio2.click()
def radio2Selected = radio2.isSelected()
def radio1AfterRadio2 = radio1.isSelected()
then: "seul un radio button doit être sélectionné à la fois"
radio1Selected == true
radio2Selected == true
radio1AfterRadio2 == false
}
@Unroll
def "test paramétré avec différentes données: #testData"() {
given: "je navigue vers la page de saisie"
navigateToTextInputPage()
when: "je saisis les données de test"
WebElement editText = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.className("android.widget.EditText")
)
)
editText.clear()
editText.sendKeys(testData)
then: "le texte doit être correctement affiché"
editText.getText() == testData
where: "les données de test sont"
testData << [
"Test simple",
"Test avec des chiffres 123",
"Test avec caractères spéciaux !@#",
"Test très long pour vérifier la capacité du champ de texte à gérer du contenu étendu"
]
}
def "gestion d'erreurs avec timeout"() {
when: "je cherche un élément qui n'existe pas"
try {
wait.until(
ExpectedConditions.visibilityOfElementLocated(
AppiumBy.id("element.inexistant")
)
)
} catch (Exception e) {
// Exception attendue
}
then: "le test ne doit pas planter"
driver != null
driver.getPageSource() != null
}
// ✅ Méthodes utilitaires privées
private void navigateToControlsPage() {
driver.findElement(AppiumBy.androidUIAutomator('new UiSelector().text("Views")')).click()
WebElement controlsOption = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator(
'new UiScrollable(new UiSelector().scrollable(true))' +
'.scrollIntoView(new UiSelector().text("Controls"))'
)
)
)
controlsOption.click()
driver.findElement(
AppiumBy.androidUIAutomator('new UiSelector().text("1. Light Theme")')
).click()
}
private void navigateToTextInputPage() {
navigateToControlsPage()
}
private String getAppPath() {
return System.getProperty("user.dir") + "/src/test/resources/apps/android/ApiDemos-debug.apk"
}
}
Exécution des tests Spock
Les tests Spock s'exécutent comme des tests classiques avec Maven :
# Exécuter tous les tests (y compris Spock)
mvn clean test
# Exécuter seulement les tests Spock
mvn test -Dtest="*Spec"
# Exécuter un test Spock spécifique
mvn test -Dtest="LoginSpec"
- Syntaxe expressive : given/when/then plus lisible
- Tests paramétrés : @Unroll pour tester plusieurs datasets
- Mocks intégrés : pas besoin de Mockito
- Assertions puissantes : conditions multiples avec and/or
- Groovy : syntaxe plus concise que Java
Exécution avancée avec Maven
Maven offre une flexibilité exceptionnelle pour l'exécution de tests Appium. Cette section détaille les commandes avancées, les profils de configuration, et les techniques d'optimisation pour différents scénarios d'exécution.
Commandes de base
Ces commandes constituent le socle de l'exécution quotidienne des tests :
# ✅ Compilation et exécution complète
mvn clean compile test
# ✅ Exécution rapide sans nettoyage
mvn test
# ✅ Ignorer les échecs de tests (pour CI/CD)
mvn test -Dmaven.test.failure.ignore=true
# ✅ Exécution en mode offline (sans téléchargement)
mvn test -o
Exécution sélective
Pour des cycles de développement plus rapides, l'exécution sélective est essentielle :
# ✅ Exécuter une classe de test spécifique
mvn test -Dtest=LoginTests
# ✅ Exécuter une méthode de test spécifique
mvn test -Dtest=LoginTests#testValidLogin
# ✅ Exécuter plusieurs classes
mvn test -Dtest=LoginTests,NavigationTests,CheckoutTests
# ✅ Exécuter par pattern de nom
mvn test -Dtest="*Login*"
# ✅ Exécuter par package
mvn test -Dtest="com.company.mobile.tests.smoke.*"
# ✅ Exclure certains tests
mvn test -Dtest="!*Integration*"
Configuration d'environnement
Adapter l'exécution selon l'environnement cible :
# ✅ Spécifier la plateforme de test
mvn test -Dtest.platform=android
mvn test -Dtest.platform=ios
# ✅ Configurer le serveur Appium
mvn test -Dappium.server.url=http://192.168.1.100:4723
# ✅ Ajuster les timeouts
mvn test -Dimplicit.wait=15 -Dexplicit.wait=30
# ✅ Spécifier l'application à tester
mvn test -Dapp.path=/path/to/your/app.apk
# ✅ Configurer le device
mvn test -Ddevice.name="Pixel_6_API_33"
Profils Maven avancés
Définissez des profils complexes dans votre pom.xml pour différents environnements :
<profiles>
<!-- ✅ Profil de développement local -->
<profile>
<id>dev</id>
<properties>
<test.platform>android</test.platform>
<appium.server.url>http://127.0.0.1:4723</appium.server.url>
<device.name>Android Emulator</device.name>
<implicit.wait>10</implicit.wait>
</properties>
</profile>
<!-- ✅ Profil d'intégration continue -->
<profile>
<id>ci</id>
<properties>
<test.platform>android</test.platform>
<appium.server.url>http://appium-grid:4723</appium.server.url>
<device.name>ci-emulator</device.name>
<implicit.wait>15</implicit.wait>
<maven.test.failure.ignore>false</maven.test.failure.ignore>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<reportsDirectory>${project.build.directory}/ci-reports</reportsDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- ✅ Profil de tests de performance -->
<profile>
<id>performance</id>
<properties>
<test.platform>android</test.platform>
<parallel.tests>true</parallel.tests>
<thread.count>3</thread.count>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>classes</parallel>
<threadCount>${thread.count}</threadCount>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Exécution avec profils
# ✅ Utiliser le profil de développement
mvn clean test -Pdev
# ✅ Utiliser le profil CI
mvn clean test -Pci
# ✅ Combiner plusieurs profils
mvn clean test -Pci,performance
# ✅ Surcharger des propriétés de profil
mvn test -Pdev -Ddevice.name="Pixel_7_API_34"
Optimisation des performances
Techniques pour accélérer l'exécution des tests :
# ✅ Configuration JVM optimisée
export MAVEN_OPTS="-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+UseZGC"
# ✅ Exécution parallèle par classes (attention aux resources)
mvn test -Dparallel=classes -DthreadCount=2
# ✅ Exécution parallèle par méthodes
mvn test -Dparallel=methods -DthreadCount=4
# ✅ Compilation incrémentale
mvn test -Dmaven.compiler.useIncrementalCompilation=true
# ✅ Skip des étapes non nécessaires
mvn test -DskipTests=false -Dmaven.javadoc.skip=true -Dmaven.source.skip=true
Intégration avec Allure Reports
Génération automatique de rapports visuels :
# ✅ Exécuter les tests avec génération des données Allure
mvn clean test
# ✅ Générer le rapport HTML
mvn allure:report
# ✅ Ouvrir le rapport dans le navigateur
mvn allure:serve
# ✅ Pipeline complet
mvn clean test allure:report allure:serve
# ✅ Générer le rapport avec historique
mvn allure:report -Dallure.results.directory=target/allure-results
Debugging et logs avancés
# ✅ Mode debug Maven complet
mvn test -X -Dappium.log.level=debug
# ✅ Logs détaillés sans le mode debug
mvn test -Dorg.slf4j.simpleLogger.defaultLogLevel=debug
# ✅ Capturer la sortie dans un fichier
mvn test -l test-execution.log
# ✅ Afficher les propriétés système utilisées
mvn test -Dtest=LoginTests -X | grep -E "test\.|appium\.|device\."
Scripts d'automatisation
Créez des scripts pour standardiser l'exécution :
Script bash pour Linux/Mac (run-tests.sh)
#!/bin/bash
# Configuration par défaut
PLATFORM="android"
PROFILE="dev"
TEST_CLASS=""
# Gestion des arguments
while [[ $# -gt 0 ]]; do
case $1 in
-p|--platform)
PLATFORM="$2"
shift 2
;;
--profile)
PROFILE="$2"
shift 2
;;
-t|--test)
TEST_CLASS="$2"
shift 2
;;
*)
echo "Option inconnue: $1"
exit 1
;;
esac
done
echo "🚀 Lancement des tests Appium"
echo "Plateforme: $PLATFORM"
echo "Profil: $PROFILE"
echo "Classe de test: ${TEST_CLASS:-'Toutes'}"
# Construction de la commande Maven
MVN_CMD="mvn clean test -P$PROFILE -Dtest.platform=$PLATFORM"
if [ ! -z "$TEST_CLASS" ]; then
MVN_CMD="$MVN_CMD -Dtest=$TEST_CLASS"
fi
echo "Commande: $MVN_CMD"
echo ""
# Exécution
$MVN_CMD
# Génération du rapport si les tests sont passés
if [ $? -eq 0 ]; then
echo "✅ Tests réussis - Génération du rapport Allure"
mvn allure:report allure:serve
else
echo "❌ Échec des tests"
exit 1
fi
Utilisation du script
# ✅ Rendre le script exécutable
chmod +x run-tests.sh
# ✅ Exécuter avec paramètres
./run-tests.sh --platform android --profile dev --test LoginTests
# ✅ Exécuter avec configuration par défaut
./run-tests.sh
- Adapter l'exécution selon l'environnement (dev, CI, production)
- Optimiser les performances avec l'exécution parallèle
- Générer des rapports automatiquement avec Allure
- Automatiser avec des scripts personnalisés
- Débugger efficacement avec des logs détaillés
Exemple de test JUnit avec code moderne
JUnit reste l'un des frameworks de test les plus populaires pour Java. Voici comment l'utiliser efficacement avec Appium en utilisant du code moderne qui fonctionne avec les versions récentes.
Configuration JUnit dans le pom.xml
Ajoutez JUnit 5 (Jupiter) à votre projet pour bénéficier des dernières fonctionnalités :
<!-- ✅ JUnit 5 (Jupiter) - Version moderne -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<!-- ✅ Support pour les tests paramétrés -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
Classe de test JUnit moderne
Voici un exemple complet utilisant JUnit 5 avec du code Appium 2025 qui fonctionne :
package com.company.mobile.tests;
import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.net.URL;
import java.time.Duration;
public class LoginTest {
// ✅ Driver moderne sans paramètre générique
private static AndroidDriver driver;
private static WebDriverWait wait;
@BeforeAll
static void setupClass() throws Exception {
// ✅ Configuration avec capabilities modernes
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("platformName", "Android");
caps.setCapability("appium:deviceName", "Android Emulator");
caps.setCapability("appium:automationName", "UiAutomator2");
caps.setCapability("appium:app", getAppPath());
caps.setCapability("appium:autoGrantPermissions", true);
caps.setCapability("appium:noReset", false);
caps.setCapability("appium:newCommandTimeout", 300);
// ✅ URL moderne sans /wd/hub
driver = new AndroidDriver(new URL("http://127.0.0.1:4723"), caps);
// ✅ Configuration des timeouts
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
wait = new WebDriverWait(driver, Duration.ofSeconds(15));
}
@AfterAll
static void tearDownClass() {
if (driver != null) {
driver.quit();
}
}
@BeforeEach
void setUp() {
// Reset de l'application avant chaque test
driver.resetApp();
}
@Test
@DisplayName("Le formulaire de login doit être visible au démarrage")
void testLoginFormVisible() {
// ✅ Navigation vers la section App
WebElement appSection = driver.findElement(
AppiumBy.androidUIAutomator("new UiSelector().text(\"App\")")
);
Assertions.assertTrue(appSection.isDisplayed(),
"La section App doit être visible au démarrage");
// ✅ Clic avec vérification
appSection.click();
// ✅ Attente explicite pour le chargement
WebElement activitySection = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator("new UiSelector().text(\"Activity\")")
)
);
Assertions.assertTrue(activitySection.isDisplayed(),
"La section Activity doit être accessible après clic sur App");
}
@Test
@DisplayName("Navigation vers les contrôles de saisie")
void testNavigationToControls() {
// ✅ Navigation vers Views > Controls
WebElement viewsSection = driver.findElement(
AppiumBy.androidUIAutomator("new UiSelector().text(\"Views\")")
);
viewsSection.click();
// ✅ Scroll pour trouver Controls
WebElement controlsOption = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator(
"new UiScrollable(new UiSelector().scrollable(true))" +
".scrollIntoView(new UiSelector().text(\"Controls\"))"
)
)
);
controlsOption.click();
// ✅ Sélectionner Light Theme
WebElement lightTheme = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator("new UiSelector().text(\"1. Light Theme\")")
)
);
lightTheme.click();
// ✅ Vérifier la présence du champ EditText
WebElement editText = wait.until(
ExpectedConditions.visibilityOfElementLocated(
AppiumBy.className("android.widget.EditText")
)
);
Assertions.assertTrue(editText.isDisplayed(),
"Le champ de saisie doit être visible");
}
@Test
@DisplayName("Saisie de texte dans le champ EditText")
void testTextInputFunctionality() {
// Navigation préparatoire
navigateToTextInput();
// ✅ Localiser le champ EditText
WebElement editText = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.className("android.widget.EditText")
)
);
// ✅ Test de saisie moderne
String testText = "Test JUnit avec Appium moderne!";
editText.clear();
editText.sendKeys(testText);
// ✅ Vérification avec assertion JUnit 5
String actualText = editText.getText();
Assertions.assertEquals(testText, actualText,
"Le texte saisi doit correspondre exactement");
// ✅ Fermer le clavier Android
try {
driver.hideKeyboard();
} catch (Exception e) {
// Clavier déjà fermé ou non disponible
System.out.println("Clavier non disponible ou déjà fermé");
}
}
@Test
@DisplayName("Test des contrôles CheckBox et RadioButton")
void testControlElements() {
navigateToTextInput();
// ✅ Test de la CheckBox
WebElement checkbox = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/check1")
);
boolean initialState = checkbox.isSelected();
checkbox.click();
boolean newState = checkbox.isSelected();
Assertions.assertNotEquals(initialState, newState,
"L'état de la checkbox doit changer après le clic");
// ✅ Test des RadioButtons
WebElement radio1 = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/radio1")
);
WebElement radio2 = driver.findElement(
AppiumBy.id("io.appium.android.apis:id/radio2")
);
// Test de sélection exclusive
radio1.click();
Assertions.assertTrue(radio1.isSelected(),
"Radio 1 doit être sélectionné");
radio2.click();
Assertions.assertTrue(radio2.isSelected(),
"Radio 2 doit être sélectionné");
Assertions.assertFalse(radio1.isSelected(),
"Radio 1 ne doit plus être sélectionné quand Radio 2 est cliqué");
}
@ParameterizedTest
@DisplayName("Test paramétré avec différents textes")
@ValueSource(strings = {
"Test simple",
"Test avec chiffres 123",
"Test avec caractères !@#$%",
"Test très long pour vérifier la capacité du champ"
})
void testParameterizedTextInput(String testData) {
navigateToTextInput();
WebElement editText = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.className("android.widget.EditText")
)
);
editText.clear();
editText.sendKeys(testData);
String actualText = editText.getText();
Assertions.assertEquals(testData, actualText,
() -> "Le texte '" + testData + "' doit être correctement saisi");
}
@Test
@DisplayName("Gestion des timeouts et éléments introuvables")
void testTimeoutHandling() {
// ✅ Test avec élément qui n'existe pas
Assertions.assertThrows(
org.openqa.selenium.TimeoutException.class,
() -> {
wait.until(
ExpectedConditions.visibilityOfElementLocated(
AppiumBy.id("element.qui.nexiste.pas")
)
);
},
"Une TimeoutException doit être levée pour un élément inexistant"
);
// ✅ Vérifier que le driver est toujours utilisable
Assertions.assertNotNull(driver.getPageSource(),
"Le driver doit rester fonctionnel après un timeout");
}
@Test
@DisplayName("Test de navigation avec gestion d'erreurs")
void testNavigationWithErrorHandling() {
try {
// Navigation normale
WebElement viewsSection = driver.findElement(
AppiumBy.androidUIAutomator("new UiSelector().text(\"Views\")")
);
viewsSection.click();
// Vérification du succès
WebElement buttonsOption = wait.until(
ExpectedConditions.visibilityOfElementLocated(
AppiumBy.androidUIAutomator("new UiSelector().textContains(\"Button\")")
)
);
Assertions.assertTrue(buttonsOption.isDisplayed(),
"Au moins un élément 'Button' doit être visible dans Views");
} catch (Exception e) {
// ✅ Capture d'écran en cas d'erreur
takeScreenshotOnFailure("testNavigationWithErrorHandling");
// Re-lancer l'exception pour marquer le test comme échoué
throw e;
}
}
// ✅ Méthodes utilitaires privées
private void navigateToTextInput() {
driver.findElement(
AppiumBy.androidUIAutomator("new UiSelector().text(\"Views\")")
).click();
WebElement controlsOption = wait.until(
ExpectedConditions.elementToBeClickable(
AppiumBy.androidUIAutomator(
"new UiScrollable(new UiSelector().scrollable(true))" +
".scrollIntoView(new UiSelector().text(\"Controls\"))"
)
)
);
controlsOption.click();
driver.findElement(
AppiumBy.androidUIAutomator("new UiSelector().text(\"1. Light Theme\")")
).click();
}
private void takeScreenshotOnFailure(String testName) {
try {
byte[] screenshot = driver.getScreenshotAs(org.openqa.selenium.OutputType.BYTES);
String timestamp = java.time.LocalDateTime.now()
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"));
String fileName = String.format("target/screenshots/%s_%s_FAILED.png",
testName, timestamp);
java.nio.file.Files.createDirectories(
java.nio.file.Paths.get("target/screenshots")
);
java.nio.file.Files.write(
java.nio.file.Paths.get(fileName),
screenshot
);
System.out.println("📸 Screenshot capturé: " + fileName);
} catch (Exception e) {
System.err.println("❌ Erreur capture d'écran: " + e.getMessage());
}
}
private static String getAppPath() {
return System.getProperty("user.dir") +
"/src/test/resources/apps/android/ApiDemos-debug.apk";
}
}
Configuration Maven pour JUnit 5
Assurez-vous que votre plugin Surefire supporte JUnit 5 :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<!-- ✅ Configuration pour JUnit 5 -->
<useModulePath>false</useModulePath>
</configuration>
</plugin>
Exécution des tests JUnit
# ✅ Exécuter tous les tests JUnit
mvn test
# ✅ Exécuter une classe de test spécifique
mvn test -Dtest=LoginTest
# ✅ Exécuter une méthode de test spécifique
mvn test -Dtest=LoginTest#testLoginFormVisible
# ✅ Exécuter seulement les tests paramétrés
mvn test -Dtest=LoginTest#testParameterizedTextInput
- @DisplayName : descriptions de test plus lisibles
- @ParameterizedTest : tests avec plusieurs jeux de données
- Assertions améliorées : messages d'erreur plus clairs
- @BeforeAll/@AfterAll : gestion du cycle de vie optimisée
- Gestion d'exceptions : assertThrows() pour tester les erreurs
- Lambda dans assertions : messages d'erreur dynamiques
- Code Appium 2025 : WebElement, AppiumBy, capabilities correctes
- Tests robustes : attentes explicites, gestion d'erreurs
- JUnit 5 : annotations modernes et fonctionnalités avancées
- Screenshots automatiques : capture en cas d'échec
- Tests paramétrés : validation avec plusieurs datasets
Ressources utiles et écosystème Appium
Cette section regroupe les ressources essentielles pour continuer à développer vos compétences Appium, rester à jour avec les évolutions du framework, et bénéficier de l'expérience de la communauté.
Documentation officielle
- Documentation officielle Appium - Source de référence pour toutes les fonctionnalités
- Appium Java Client GitHub - Code source et exemples pour le client Java
- API Reference Appium 2.x - Documentation technique détaillée
- Documentation Selenium WebDriver - Base commune avec Appium
Frameworks de test compatibles
- TestNG Documentation - Framework utilisé dans nos exemples
- JUnit 5 User Guide - Framework alternatif moderne
- Spock Framework - Tests expressifs en Groovy
- Cucumber - Tests orientés BDD
Communauté et support
- Forum officiel Appium - Questions et discussions communautaires
- StackOverflow - Tag Appium - Questions techniques
- GitHub Issues Appium - Signalement de bugs
- Discord Appium - Chat en temps réel
Outils complémentaires
- Appium Inspector - Exploration visuelle des éléments UI
- Allure Reports - Génération de rapports visuels
- Apache Maven - Gestionnaire de build et dépendances
- Android Studio - SDK et émulateurs Android
Services cloud pour tests mobiles
- BrowserStack App Automate - Tests sur appareils réels cloud
- Sauce Labs Mobile Testing - Plateforme de tests mobile
- AWS Device Farm - Service de test AWS
- Firebase Test Lab - Tests Android sur infrastructure Google
Blogs et ressources avancées
- Appium Pro - Articles techniques avancés
- Medium - Tag Appium - Articles de la communauté
- Chaîne YouTube Appium - Tutoriels vidéo officiels
Livres recommandés
- "Appium Essentials" par Manoj Hans - Introduction complète à Appium
- "Mobile Test Automation with Appium" par Nishant Verma - Techniques avancées
- "Selenium WebDriver 3 Practical Guide" par Unmesh Gundecha - Base Selenium applicable à Appium
Continuer à apprendre
Pour maintenir vos compétences Appium à jour dans un écosystème en constante évolution :
- Suivez les release notes d'Appium pour connaître les nouvelles fonctionnalités
- Participez aux discussions sur les forums et GitHub pour partager votre expérience
- Expérimentez avec les bêta pour anticiper les évolutions
- Contribuez aux projets open source pour approfondir votre compréhension
- Organisez des sessions de partage dans votre équipe ou entreprise
🎉 Félicitations ! Vous avez maintenant toutes les clés pour maîtriser Appium
Cette formation vous a donné une base solide avec du code moderne et des bonnes pratiques éprouvées. L'investissement en temps de ce guide vous fera économiser les 1800€ de formation traditionnelle, tout en vous donnant une maîtrise pratique immédiatement opérationnelle.
Ce que vous avez appris :
- Installation et configuration complète d'un environnement Appium moderne
- Utilisation du code Appium 2025 avec WebElement et AppiumBy
- Configuration Maven professionnelle avec toutes les dépendances
- Écriture de tests robustes avec TestNG, JUnit et Spock
- Gestion des émulateurs Android et simulateurs iOS
- 50 solutions aux erreurs les plus courantes
- Intégration dans des pipelines CI/CD
Prochaines étapes recommandées :
- Créez votre premier projet avec le code Maven fourni
- Téléchargez l'APK ApiDemos et reproduisez les exemples
- Adaptez les tests à votre application spécifique
- Configurez l'intégration CI/CD avec GitHub Actions ou GitLab
- Rejoignez la communauté Appium pour continuer à apprendre
Vous êtes maintenant autonome pour développer une suite de tests Appium professionnelle. Le code que vous avez appris fonctionne réellement et vous évitera les frustrations des tutoriels obsolètes.
Bonne continuation dans votre parcours d'automatisation des tests mobiles !