Tests E2E en Angular 2 de zéro à héros (partie finale)
Chers futurs maîtres des tests E2E en Angular 2.
C’est tout. A la fin de cette leçon, vous aurez enfin tous les outils pour créer des tests fonctionnels pour vos applications Angular 2. Plus d’excuses : Vous avez le pouvoir !
Nous allons d’abord nous familiariser avec les Locators puis nous verrons à quel point les Page Objects peuvent être impressionnants, suivis par la façon de gérer l’asynchronisme et enfin la partie la plus facile qui est le déclenchement des Actions.
Si vous n’avez pas bien les bases, dirigez-vous là sinon vous serez un peu perdu.
Locators
Une des choses les plus importantes, si ce n’est la plus importante, dans les tests E2E est de trouver les éléments que vous voulez tester dans votre vue. La plupart du temps, vous vous poserez la question « pourquoi ne puis-je pas trouver cet élément **** ? » suivie d’un « oooohhhh ».
Vous avez plusieurs façons de le faire. La plupart d’entre elles dépendent de votre application. Afin d’obtenir vos éléments, vous utiliserez une gamme de Locators. La plupart du temps, vous pouvez trouver vos éléments par :
- Nom de la classe.
- Id.
- Modèle.
- Binding.
Pour les prochains tests, nous utiliserons ce modèle.html:
<div class="parent2"> <div class="parent1"> <div class="nested-class" style="color:blue;"> I am a nested element </div> </div></div>
Faisons un focus sur nested-class et nested-id.
By Class:
Nous saisissons ici notre élément en utilisant element(by.css(selector)) puis nous testons s’il est présent ou non.
By Id:
it("should find the nested id", () => { let elem = element(by.id("nested-id")); expect(elem.getText()).toBe("I am a nested element");});
Nous saisissons ici notre élément en utilisant element(by.id(elem-id)) puis nous testons s’il est présent ou non.
Les localisateurs suivants un très utile dans AngularJS mais pas encore implémenté dans Angular 2 donc gardez-les de côté pour le moment.
By Model:
it("should find the model", () => { let elem = element(by.model("modelToFind")); expect(elem.isPresent()).toBeTruthy();});
By Bindings:
it("should find the binding", () => { let elem = element(by.model("bindingToFind")); expect(elem.isPresent()).toBeTruthy();});
Pour déboguer vos tests, vous pouvez simplement ajouter « browser.pause() » dans votre test, vous pourrez exécuter toutes les instructions précédentes et vous arrêter où vous voulez.
Une fois qu’il atteint votre pause, vous aurez un écran similaire à celui-ci:
Comme vous pouvez le voir dans cette image, afin d’entrer dans le siège du conducteur, vous devez taper repl.
Maintenant disons que vous n’avez pas de test et que vous voulez juste jouer avec Protractor. Vous pouvez simplement taper dans votre terminal:
protractor --elementExplorer
Si vous avez des problèmes avec votre chemin, vous pouvez taper:
./node_modules/protractor/bin/elementexplorer.js
Pas besoin de taper repl cette fois, il suffit d’utiliser l’objet navigateur et vous êtes prêt à naviguer!
Objets pages
Que faire si vous avez des tests qui partagent le même scénario ? Allez-vous copier-coller votre code partout ? Et si ce scénario change ? Maintenant vous devez passer par tous les fichiers et faire les modifications.
C’est là que les Pages Objects deviennent très utiles. Ecrivez une fois, partagez partout !
Un Page Object est un objet qui contient les éléments et les scénarios concernant une page.
Premièrement un Page Object très simple :
export class HomePage { nestedClass; constructor() { this.nestedClass = element(by.css(".nested-class")); }}
Puis nous l’utilisons dans notre test :
Nous importons le Page Object, créons une instance puis utilisons sa propriété.
Aventures asynchrones
Maintenant mes amis, vous pouvez accéder à tous les éléments de votre page ! Je veux dire presque :).
Il y aura quelques cas particuliers.
Si vous avez eu la (mal)chance de travailler avec jQuery, vous devez être familier avec document.ready().
De par la nature asynchrone de JavaScript, il y aura des cas où vous essayerez d’accéder à un élément avant qu’il ne soit encore apparu sur la page.
Pour gérer cela, vous devrez utiliser une fonctionnalité de Protractor afin d’attendre que votre élément soit prêt avant de le rechercher.
Voici un exemple affichant un bouton après une expiration de délai.
D’abord la classe qui contient le timeout:
export class Home { isHidden = true; triggerTimeOut = ((){ setTimeout(() => this.isHidden = false, 2250) })}
Puis le template.html:
Nous avons ici un bouton qui va déclencher notre timeout, une fois le timeout expiré, le texte est affiché.
Voici les tests.
Nous trouvons notre bouton, nous cliquons dessus, nous essayons de trouver notre texte MAIS nous nous attendons à ce qu’il ne soit pas présent.
Et voici la façon dont nous gérons ce cas ;).
Nous utilisons « browser.wait » combiné avec « browser.isElementPresent » pour tester notre Locator. Après 5 secondes, le reste du code est exécuté. N’oubliez pas de mettre un timer ici sinon vos tests seront bloqués pour toujours !
Alors si l’un de vos éléments est censé être ici mais que vous ne pouvez pas l’obtenir, votre instinct devrait vous dire de vous souvenir de ce que vous venez de lire ici.
Actions
Maintenant que vous avez votre précieux élément, vous avez fait 90% du travail !
Si vous ne le trouvez pas, c’est soit que votre application ne fonctionne pas comme elle le devrait (c’est pourquoi nous faisons des tests), soit que vous devez vous améliorer en matière de tests et passer moins de temps sur Pokemon GO à chasser des dratinis près d’une rivière à 1 heure du matin (nous sommes tous passés par là…).
Poursuivons avec les actions que vous pouvez utiliser sur un élément. Les voici :
Nous utilisons Protractor qui s’appuie sur WebDriver. Si vous avez besoin d’actions plus fantaisistes, vous pouvez jeter un coup d’œil à ce qui est disponible ici.
Testons certaines d’entre elles.
Pour le modèle.html:
<input type="text" />
Nous allons jouer un peu avec la saisie de texte. Question rapide, que fait ce test (ne lisez pas la description) ?
Solution : Nous obtenons notre entrée, nous tapons « Some text » à l’intérieur, nous testons que nous avons obtenu la valeur définie, nous l’effaçons et enfin nous testons que la valeur est vide.
Légitimement, nous pouvons nous demander quelle est la meilleure façon de déclencher des actions ? Ce lien ici montre l’un des défauts de l’utilisation de JavaScript au lieu de WebDriver.
Sure écrire en JavaScript est beaucoup plus compact mais il vient avec certains risques!
Vous pouvez faire tout ce que vous voulez avec un élément. La meilleure façon de le tester est d’utiliser les matchers qui sont disponibles. Pourquoi ? Parce qu’ils sont élégants et proches du langage humain, exemple :
expect(apples.length !== 0).toBe(true);
expect(apples).not.toBeEmpty();
Conclusion
C’était le dernier post de cette série, à l’heure actuelle vous avez 90% des compétences pour tester vos applications Angular 2. Vous obtiendrez les 10% restants par l’expérience. Rappelez-vous, d’abord obtenir vos éléments en utilisant les Locators, puis mettre celui qui pourrait être répliqué dans un Page Object, si vous ne pouvez pas trouver votre élément et que vous êtes sûr qu’il est ici, c’est peut-être parce qu’il n’est pas encore apparu et que vous devez gérer l’asynchronisme. Enfin, testez le **** de vos éléments avec des actions.