Nous automatisons les tests d'interface des applications Android en utilisant le modèle d'objet de page

image

Le modèle d'objet de page est apparu dans les tests Web et s'est révélé très bon là-bas. Quand j'ai commencé à automatiser les tests pour les applications Android, la première chose à laquelle j'ai pensé. J'ai cherché des informations sur le réseau, demandé à mes collègues et, en principe, je n'ai pas trouvé de raisons de ne pas essayer. Je propose de voir ce qui en est sorti.

L'objet Page classique implique deux niveaux d'abstraction: les éléments de page et les tests. J'en souligne un autre: la logique métier. Je note que la façon dont vous construisez votre framework affectera grandement la facilité d'écriture des tests à l'avenir, ainsi que leur support. J'essaie de faire ressembler le code de test à un scénario de test normal écrit par un testeur ordinaire. C'est-à-dire Je pars de la fin:

  1. J'écris un code de cas de test beau et clair,
  2. J'implémente des méthodes du cas de test dans la couche logique métier,
  3. Je décris les éléments nécessaires au test.

Cette approche est bonne car nous ne faisons rien de plus - le framework est construit autant que nécessaire pour que les tests fonctionnent. On peut dire que c'est le concept de MVP dans les tests: ils ont rapidement fait une pièce, et elle a déjà commencé à apporter des bénéfices. Si vous écrivez d'abord des milliers de lignes, décrivant les pages de votre application et comment interagir avec elles, et après trois mois, vous sortez du trou pour le premier clic et réalisez que vous deviez tout faire différemment, alors la plupart de votre création sera vouée à l'infini " ramasser la poussière »dans les sous-sols de git ... Un vrai testeur sait que plus tôt un bug est trouvé, moins il est cher de le corriger. Utilisez cette approche dans tout - a écrit un test en quelques heures, l'a essayé, ne l'aimait pas - l'a jeté, a appris une leçon, a continué.

L'entrée est donc:

  • Application Android pour le trading en bourse;
  • Java pour travailler dans la même pile avec les développeurs;
  • cadre de base UI Automator;
  • vous devez écrire un test de connexion dans l'application.

Préparation du projet


Depuis que j'ai essayé de m'intégrer autant que possible dans le processus de développement, je n'ai pas commencé à créer un nouveau projet. Selon la documentation , les tests instrumentaux doivent être placés dans le dossier src/androidTest/java . Dans mon cas, le collecteur a déjà été configuré, si vous avez quelque chose de mal, alors lisez la configuration de construction . Nous avons également besoin d'un environnement de développement, du SDK Android, d'un émulateur, d'outils, d'outils de plate-forme et des plates-formes nécessaires pour l'émulateur. Si vous utilisez Android Studio, tout cela peut être rapidement installé via le SDK Manager:



Couche de test


Comme je l'ai écrit ci-dessus, nous automatiserons le test de connexion dans l'application. N'oubliez pas que le code devrait ressembler à un cas de test normal:

Condition: lancez l'application.
Étape 1: connectez-vous à l'aide du compte myLogin / myPassword.
Étape 2: vérifiez le nom de l'utilisateur actuel.
Résultat attendu: l'utilisateur actuel est Ivan Ivanov.

Petit avertissement: selon les meilleures pratiques du test de conception, dans la condition préalable, vous devez créer / trouver un compte. J'ai omis ce moment pour la simplicité de l'exemple.

Notre classe ressemblera à ceci:

 @RunWith(AndroidJUnit4.class) public class LoginTests { private TestApplication myApp; @Before public void setUp() { myApp = new TestApplication(); } @Test public void testLogin() { myApp.login("myLogin","myPassword"); String currentUser = myApp.getCurrentUserName(); assertEquals("Wrong name", " ", currentUser); } @After public void tearDown() { myApp.close(); } } 

Logique métier


Le test utilise la classe TestApplication() et ses deux méthodes: login() et getCurrentUserName() . De plus, vous avez besoin d'un constructeur de classe (qui y lance l'application) et de la méthode close() . Le front est clair:

 public class TestApplication { private UiDevice device; private PageObject page; public TestApplication() { } public void login(String login, String password) { } public String getCurrentUserName() { return "" } public void close() { } } 

Une instance de notre classe aura deux variables:

  • device , appartenant à la classe android.support.test.uiautomator.UiDevice - à travers lui, nous interagissons avec notre appareil;
  • page , la classe PageObject , que nous allons créer dans la section suivante.

Commençons par le constructeur. Dans ce document, créez des instances de nos variables et exécutez l'application:

 public TestApplication() { // Connect to device device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.pressHome(); // Get launch intent String packageName = InstrumentationRegistry.getTargetContext() .getPackageName(); Context context = InstrumentationRegistry.getContext(); Intent intent = context.getPackageManager() .getLaunchIntentForPackage(packageName) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Stat application context.startActivity(intent); // Get page objects page = new PageObject(device, packageName); } 

Quelques conseils pour lancer l'application
Pour plus de contrôle sur l'application en cours de test, vous pouvez ajouter des attentes quant au démarrage du lanceur (si vous exécutez l'émulateur "à froid") et l'application elle-même. Ceci est également conseillé dans la documentation .

Remarque: l'exécution de l'application via android.content.Context.getTargetContext() ne convient que si vos tests sont dans le même projet que l'application elle-même. Si séparément, il sera nécessaire de parcourir le menu.

La logique métier du test est les étapes spécifiques que l'utilisateur doit suivre pour obtenir un résultat significatif (pour l'utilisateur). La connexion sous votre propre échographie est un résultat significatif. Étapes: cliquez sur le bouton «Connexion», entrez le nom d'utilisateur dans le champ «Connexion», entrez le mot de passe dans le champ «Mot de passe», cliquez sur le bouton «Connexion». Ainsi, notre méthode est remplie d'étapes:

 public void login(String login, String password) { page.login().click(); page.loginEntry().setText(login); page.passwordEntry().setText(password); page.signIn().click(); } 

Pour obtenir l'utilisateur actuel, tout est plus simple, il suffit d'obtenir la valeur du champ:

 public String getCurrentUserName() { return page.currentUserName().getText(); } } 

Et pour fermer l'application, cliquez simplement sur le bouton Accueil:

 public void close() { device.pressHome(); } 

Description des éléments de page


Le concept de cette couche est qu'elle doit renvoyer des éléments prêts à l'emploi (dans notre contexte, il s'agit de la classe android.support.test.uiautomator.UiObject2 ). Autrement dit, le consommateur ne devrait pas se soucier de l'état de l'objet, s'il est revenu, vous pouvez immédiatement interagir avec lui: cliquez, remplissez ou lisez le texte. C'est une conséquence importante - dans cette couche, nous réaliserons les attentes:

 private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); } 

La méthode définie ci-dessus sera utilisée par l'interface publique de notre classe PageObject . Exemple pour le champ de connexion:

 public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); } 

Reste à déterminer le sélecteur par lequel nous trouverons le champ. L'instance de android.support.test.uiautomator.BySelector obtenue de la manière la plus pratique en utilisant les méthodes statiques de la classe android.support.test.uiautomator.By . Je suis d'accord avec le développement que partout, chaque fois que possible, il y aura un identifiant de ressource unique:

 private BySelector loginEntrySelector() { return By.res(packageName, "login"); } 

Il est pratique d'inspecter l'interface dans l'utilitaire uiautomatorviewer inclus dans le package d'outils (installé dans la section Préparation):



Sélectionnez l'élément souhaité et dans la section Détail du nœud, nous examinons l'ID de ressource. Il se compose du nom du package et, en fait, de l'identifiant. Nous avons obtenu le nom du package dans le constructeur de la classe TestApplication l' TestApplication utilisé lors de la création de PageObject .

Code complet:

classe PageObject
 public class PageObject { private UiDevice device; private final String packageName; private BySelector loginButtonSelector() { return By.res(packageName, "user_view"); } private BySelector loginEntrySelector() { return By.res(packageName, "login"); } private BySelector passwordEntrySelector() { return By.res(packageName, "password"); } private BySelector signInSelector() { return By.res(packageName, "btnLogin"); } private BySelector userNameSelector() { return By.res(packageName, "user_name"); } public PageObject(UiDevice device, String packageName) { this.device = device; this.packageName = packageName; } public UiObject2 login() { return getUiObject(loginButtonSelector()); } public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); } public UiObject2 passwordEntry() { return getUiObject(passwordEntrySelector()); } public UiObject2 signIn() { return getUiObject(signInSelector()); } public UiObject2 currentUserName() { return getUiObject(userNameSelector()); } private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); } } 


Exécution de tests


C'est tout, il reste à courir. Tout d'abord, connectez-vous à l'appareil ou démarrez l'émulateur. Vérifiez la connexion avec la commande adb devices (l'utilitaire adb fait partie de platform-tools):

 List of devices attached emulator-5554 device 

Si vous avez un diplôme, faites-le

 gradlew.bat connectedAndroidTest 

et apprécier comment "des robots injectés, pas des humains" (c).

Source: https://habr.com/ru/post/fr416397/


All Articles