Test fonctionnel sans tête avec sélénium et PhantomJS

Construisons un système permettant de réaliser des tests fonctionnels sur des applications Web, en utilisant Selenium et PhantomJS. Le système résultant nous permettra d’écrire des scénarios de test simples en JavaScript et de les tester à la fois dans des navigateurs réels et sur un simulateur sans tête..


Choix des composants

L'inconvénient évident de Selenium est qu'il nécessite un bureau graphique complet pour tous les tests..

Pour commencer, nous devons choisir un contrôle de navigateur ou un moteur d’émulation pour simuler un utilisateur final. Pendant longtemps, le principal acteur dans ce domaine a été le sélénium, et il l’est toujours. Selenium permet le contrôle automatisé de navigateurs réels sur des systèmes d'exploitation réels, ce qui constitue son principal avantage: vous pouvez être absolument certain que les tests représentent le plus fidèlement possible la réalité..

L'inconvénient évident de Selenium est qu'il nécessite un bureau graphique complet pour tous les tests. En conséquence, vos tests peuvent devenir lents. Cependant, Selenium peut être fantastique si vous disposez des ressources nécessaires pour configurer des machines virtuelles pour différents systèmes d'exploitation et les connecter ensemble..

PhantomJS se situe à l'opposé du spectre. Il s'agit d'un projet petit mais excellent, qui exécute un moteur WebKit avec un accès JavaScript complet, mais sans la partie graphique. PhantomJS est un jeu d'enfant à configurer, fonctionne sur n'importe quelle machine et est nettement plus rapide.

Selenium peut maintenant contrôler PhantomJS de la même manière que n'importe quel autre navigateur..

PhantomJS, étant un kit Web complet, couvre 90% de vos besoins en tests fonctionnels. Après tout, si votre application s'exécute correctement dans WebKit, il est probable qu'elle s'exécutera correctement dans d'autres navigateurs.. Évidemment, cela exclut Internet Explorer 6-8..

Cependant, à mesure que votre projet gagne en popularité, les 10% restants deviennent un problème important. Si votre suite de tests fonctionnels est configurée directement sur PhantomJS, il serait difficile de réécrire les tests pour Selenium..

Heureusement, récemment, vers la fin de l'année 2012, nous avons reçu un cadeau sous la forme de liaisons PhantomJS à Selenium. En d’autres termes, Selenium peut désormais contrôler PhantomJS de la même manière que tout autre navigateur..

Etant donné que Selenium, lui-même, ne nécessite aucune configuration complexe et peut fonctionner n'importe où, nous pouvons utiliser des liaisons Selenium pour contrôler PhantomJS et couvrir 90% de nos besoins en tests. Si vous avez besoin ultérieurement de tests plus puissants, vous pouvez configurer des connexions de navigateur supplémentaires à Selenium sans modifier une seule ligne de votre code..

Ainsi, notre choix de moteur de navigateur sont Selenium avec PhantomJS.

Description des tests

Selenium propose des liaisons dans la plupart des langages de programmation courants, ce qui nous permet de choisir un langage en fonction de nos besoins. C’est peut-être l’élément le plus controversé de cet article: j'estime que JavaScript est le meilleur choix pour décrire les tests fonctionnels de sites Web et d'applications Web..

  • Quelle que soit la technologie dorsale que vous utilisez, votre front-end utilisera toujours JavaScript (Ceci s’applique même si vous utilisez un langage qui compile jusqu’en JavaScript, tel que CoffeeScript ou TypeScript..). En tant que tel, JavaScript sera toujours une langue comprise par au moins une personne de votre équipe..
  • Ensuite, envisagez la possibilité que vos tests fonctionnels soient écrits par des non-programmeurs. La popularité de JavaScript sur le front-end, combinée à la capacité d'expression de créer des langages clairs spécifiques à un domaine, permet clairement à plus de personnes d'écrire des tests fonctionnels.
  • Enfin, il est naturel de contrôler un navigateur de test avec JavaScript, étant donné qu’il est hautement asynchrone et que nous contrôlons le navigateur au quotidien..

Les liaisons Selenium pour JavaScript s'appellent, webdriverjs. Bien que le projet soit moins mature que les pilotes officiellement pris en charge pour Java, C #, Ruby et Python, il contient néanmoins déjà la plupart des fonctionnalités dont nous avons besoin..

Test en cours d'exécution

Pour les besoins de cet article, Mocha avec Chai ont été sélectionnés.

Enfin, nous avons besoin d’un exécuteur de tests ou d’une application pour exécuter les tests par nom et imprimer en sortie le résultat, tout en notant le nombre de tests réussis ou échoués. Ce testeur doit également proposer une bibliothèque d’assertions, qui permet au codeur d’exprimer si un test réussit ou échoue..

Le choix est absolument gratuit ici. Il y a beaucoup de coureurs de test JavaScript, mais pour les besoins de cet article, Mocha avec Chai ont été sélectionnés. Mocha offre une flexibilité considérable, une grande variété de formats de sortie et la syntaxe populaire de type Jasmine. Chai vous permet d’écrire des assertions descriptives de type BDD.


Installer

Voici la pile finale que nous utiliserons:

  1. Moka - coureur de test
  2. Chai - bibliothèque d'assertion
  3. webdriverjs - liaisons de contrôle de navigateur
  4. Selenium - Abstraction du navigateur et fonctionnement de l'usine
  5. PhantomJS - navigateur rapide sans tête

Node.js et npm

Comme la majeure partie de notre pile est basée sur JavaScript, nous avons besoin de node.js et de npm. Ces deux outils sont des outils courants dans la communauté et je suppose que vous les avez déjà configurés. Sinon, utilisez le programme d'installation sur le site Web de node.js. Ne t'inquiète pas en cas de problème, de nombreux guides d'installation de nœuds sont disponibles sur le Web..

Moka, chai et webdriverjs

Tous les trois peuvent être installés, en utilisant npm:

sudo npm installer -g mocha chai webdriverjs

Vous pouvez également les installer localement dans le répertoire où se trouvent vos tests:

npm installez mocha chai webdriverjs

Sélénium

Téléchargez Selenium Server. Il est distribué comme un seul pot fichier que vous exécutez simplement:

java -jar sélénium-serveur-standalone-2.28.0.jar

Dès que vous exécutez cette commande, il démarre un serveur auquel votre code de test se connectera ultérieurement. Veuillez noter que vous devrez exécuter Selenium Server chaque fois que vous exécuterez vos tests..

PhantomJS

Version rapide

Utilisation npm installer globalement PhantomJS:

sudo npm installer -g phantomjs

Autres options

Nous avons besoin d'une nouvelle version de PhantomJS - au moins 1.8. Cela signifie que les paquets fournis par votre gestionnaire de paquets (apt-get, MacPorts,…) sera probablement obsolète.

Vous pouvez installer npm sans installation globale ou utiliser d’autres méthodes manuellement. Dans ce cas, vous devrez toutefois indiquer à Selenium où vous avez placé PhantomJS chaque fois que vous exécutez Selenium:

PATH = "/ path / to / node_modules / phantomjs / bin: $ PATH" java -jar sélénium-serveur-standalone-2.28.0.jar

Tout combiner

Maintenant que nous avons toutes les pièces, nous devons tout mettre ensemble.

Rappelez-vous: avant d’exécuter des tests, vous devez exécuter Selenium Server:

java -jar sélénium-serveur-standalone-2.28.0.jar

Selenium exécutera PhantomJS en interne; tu n'as pas à t'inquiéter pour ça.

Nous devons maintenant nous connecter à Selenium à partir de notre JavaScript. Voici un exemple d'extrait de code qui établira une connexion avec Selenium et un objet ready pour contrôler notre instance Selenium:

// Utiliser webdriverjs pour créer un client Selenium var client = require ('webdriverjs'). Remote (souhaitésCapabilities: // Vous pouvez choisir d'autres navigateurs // http://code.google.com/p/selenium/wiki/. DesiredCapabilities browserName: 'phantomjs', // webdriverjs a beaucoup de sorties qui sont généralement inutiles // Cependant, en cas de problème, supprimez-le pour voir plus de détails logLevel: 'silent'); client.init ();

Maintenant, nous pouvons décrire nos tests et utiliser le client variable pour contrôler le navigateur. Une référence complète pour l'API webdriverjs est disponible dans la documentation, mais voici un court exemple:

client.url ('http://example.com/') client.getTitle (function (title) console.log ('Title is', title);); client.setValue ('# champ', 'valeur'); client.submitForm (); client.end ();

Utilisons la syntaxe Mocha et Chai pour décrire un test. nous allons tester certaines propriétés du exemple.com page Web:

describe ('Test example.com', function () before (function (done) client.init () .url ('http://example.com', done););); décrire ('Vérifier la page d'accueil' , function () it ('devrait voir le titre correct', function (done) client.getTitle (function (title) expect (title) .to.have.string ('Example Domain'); done (); );); it ('devrait voir le corps', function (done) client.getText ('p', fonction (p) expect (title) .to.have.string ('pour des exemples illustratifs dans des documents . '); done ();));; après (function (done) client.end (); done ();););

Vous voudrez peut-être en partager un client initialisation sur plusieurs fichiers de test. Créez un petit module de nœud pour l'initialiser et l'importer dans chaque fichier de test:

client.js:

exports.client = require ('webdriverjs'). remote (// Paramètres;

test.js:

var client = require ('./ client'). client; var expect = require ('chai'). expect; // effectuer des tests

Fonctionnement

Les suites de tests Mocha sont exécutées avec le moka binaire. Si vous avez suivi ce guide et installé Mocha localement, décrivez vous-même un chemin complet vers le fichier binaire: node_modules / mocha / bin / mocha.

Par défaut, Mocha considère que tout test prenant plus de deux secondes est un échec. Étant donné que nous sommes en train d'initialiser un navigateur Web et de soumettre une requête HTTP, nous devons augmenter ce délai d'attente de 5 à 10 secondes:

node_modules / mocha / bin / mocha test.js -t 10000

Si tout se passe comme prévu, vous devriez voir une sortie comme ceci:

 . ✔ 1 test terminé

Les prochaines étapes

Une fois que vous avez obtenu les résultats des tests fonctionnels souhaités, vous pouvez envisager d’améliorer votre configuration..

L'intégration continue et les tests de sélénium distribués sont deux directions évidentes.

Intégration continue

Votre objectif devrait être de minimiser le temps que vous passez à exécuter des tests..

Vous voudrez peut-être utiliser un serveur d'intégration continue entièrement automatique, qui exécutera les tests chaque fois que nécessaire, et vous informera en cas de problème..

Jenkins CI couvre le rôle d’un tel serveur dans le monde de l’open source: c’est un service pratique, puissant et facile à installer, qui exécute les tests à tout moment, dans la configuration que vous fournissez et éventuellement de nombreux autres. plus de tâches liées à la construction, telles que le déploiement de votre code sur des serveurs distants.

Si vous vous sentez aventureux, vous pouvez également expérimenter un nouveau projet, appelé GitLab CI, qui offre moins de fonctionnalités, mais qui a l'air meilleur et qui est intégré à GitLab, un clone auto-hébergé de GitHub..

Dans tous les cas, votre objectif devrait être de minimiser le temps que vous passez à exécuter des tests. Au lieu de cela, les tests doivent être exécutés automatiquement et ne doivent vous informer que si quelque chose ne va pas..

Grille de sélénium

Selenium a un certain nombre de limitations de mise en œuvre. Par exemple, vous ne pouvez pas exécuter plusieurs navigateurs sur le même ordinateur à tester avec Selenium..

En outre, vous remarquerez que, une fois que vous avez plusieurs tests, leur exécution peut devenir un processus long. Bien que l’intégration continue élimine en partie ce problème, vous pouvez toujours exécuter des tests en parallèle sur différentes machines..

Enfin, vous remarquerez bientôt que vous souhaitez tester différents navigateurs sur différents systèmes d'exploitation. Et, bien que votre code de test puisse, en théorie, communiquer avec différents serveurs Selenium, une fois que vous avez peu évolué, cette configuration doit être centralisée..

La configuration de Selenium Grid tente de fournir exactement cela. Au lieu d'avoir un serveur Selenium contrôlant plusieurs navigateurs sur une machine, vous avez un serveur Selenium, qui contrôle plusieurs nœuds Selenium, chacun ne contrôlant que quelques navigateurs sur un seul système d'exploitation..


Conclusion

La pile qui en résulte, bien que non triviale, est en réalité assez simple. L'ajout de PhantomJS à l'extrémité Selenium nous permet de commencer à utiliser Selenium sans investissement initial important, tel que la configuration de serveurs de test graphiques..

L'utilisation de JavaScript comme moteur de test garantit que nos tests resteront pertinents dans le contexte du développement Web dans un avenir prévisible..