Tests fonctionnels avec browserless : le brouteur sans tête

le mardi 3 décembre 2019

Bearstech | Dernière mise à jour : mardi 3 décembre 2019

Tester correctement votre developpement web, avec un robot sans tête, tout du long de votre développement.

Notre prochain webinar

judith and holophern testing some stuff on the web

Un site web n'est plus un gros tas de HTML servi en HTTP depuis longtemps.

Le peu de HTML sert de fondation à beaucoup de JavaScript, le tout derrière des règles de sécurité, un empilage de proxys, le tout saupoudré de services tiers directement branché via du JavaScript.

Pour recetter un site web, il faut passer par un brouteur contemporain, qui gère toutes les subtilités du couple HTML/JS et des subtilités d'HTTP.

Tester

Pour être un tant soit peu réactif, et garantir une qualité correcte tout au long du développement, il est indispensable d'avoir une intégration continue avec des tests. Le bout du tunnel avec les cycles en V est heureusement passé de mode.

Mettre en place des tests unitaires et faciles (et indispensable), tous les langages ont leurs frameworks de tests, le plus dur étant souvent d'un choisir parmi la foultitude.

Sans la tête

Les tests fonctionnels, téléguider un brouteur web pour qu'il navigue dans un site web avec diverses assertions, sont tout aussi important, mais un poil plus compliqué à mettre en place.

Il y a déjà plusieurs générations de cette technologie, après Selenium et GhostJS, suivi des outils de debug pour les smartphones.

Une norme, accompagnée par le vétéran Selenium, est apparue pour normaliser le contrôle à distance des brouteurs web : webdriver.

Les brouteurs contemporains disposent maintenant d'une option --headless pour être lancé sans écran, mais leur comportement diffèrent alors légèrement d'une utilisation classique : une partie de l'affichage est délégué à l'OS, et même à la carte 3D.

Pour avoir un rendu propre, et la possibilité de faire de jolis screenshot, il faut plein de petits détails, comme de jolies polices de caractère, et pour Linux un xvfb (X View Frame Buffer) bien configuré.

Toutes options

Browserless propose un emballage propre de Chrome avec tous les petits détails qui vont bien, comme les polices pour prendre en charge les émojis 🦊🐳🤖 (indispensable!) ou la possibilité de faire un film du jeu de test. Il est gentiment fourni avec une interface web pour déboguer.

Chrome, utilisé sur un serveur, a tendance à se vautrer sans rien dire et créer des fantômes, qui mettent rapidement le bazar sur le serveur. Browserless se charge de gérer proprement ce genre de petits accidents.

Comme browserless est poli, il respecte les spécifications de WebDriver, ce qui permet de brancher dessus les très classiques clients webdriver de son langage préféré. Il expose aussi l'interface spécifique de Chrome : puppeteer, mais autant rester standard, et ne pas s'interdire de tester d'autres brouteurs.

Le temps de la démonstration

Pour les gens pressés, la démo est disponible sur Github.

Je pars du principe que le développement du frontal est fait par un dev JavaScript, et donc testé dans le même langage. Décision arbitraire, on peut légitimement choisir le langage du l'arrière-boutique (backend ?), mais la démo perds son coté universel.

Donc, du JavaScript, ça veut dire faire des choix cornéliens, et surtout un pari sur l'espérance de vie des bibliothèques choisies. Je pars sur du Mocha (tests) et Chai (assertions), qui ont le bon gout d'être maintenus, concis et presque élégants.

La démonstration doit être pratique à déboguer sur le poste de développement, et bien passer dans la CI.

Le test fonctionnel embarque son propre docker-compose qui va lancer d'un coté l'application à tester (ici un site statique avec nginx) et de l'autre browserless et un conteneur avec les tests.

services:

  web:
    image: demo-browserless
    ports: # Just for debugging purpose
      - 8000

  browserless:
    image: browserless/chrome
    ports: # Just for debugging purpose
      - 3000

  test:
    depends_on:
      - browserless
      - web
    build:
      context: .
    entrypoint: /entrypoint.sh
    command: mocha test.js

Il est possible depuis l'hôte de se connecter au site web, et à la console de browserless.

Pour avoir quelque chose de serein et déterministe, le conteneur de test va commencer par wait-for-it, un script bash dispo dans toutes les bonnes distributions, qui attends (et timeout) la disponibilité de tous les services requis. Cette étape est effectuée par l'entrypoint.

Le test fonctionnel est minimaliste, la démo parle de browserless dans docker-compose, pas des subtilités de Webdriver et Mocha.

const driver = new Builder()
    .forBrowser('chrome')
    .withCapabilities(chromeCapabilities)
    .usingServer('http://browserless:3000/webdriver') // <-- Apply usingServer and that's it
    .build();

Webdrivers se connecte sur mon instance de browserless, plutôt qu'il lance lui même un brouteur.

describe('title', function() {
    it('should be hello', async function() {
        await driver.get('http://web:8000');
        const title = await driver.findElement(By.css('h1.title'))
        expect(await title.getText()).to.include("Hello");
    })
});

Le test se connecte au site web, avec son petit nom, charge la page et vérifie le contenu du titre, le tout avec l'élégance de la syntaxe await qui nous sauve de l'enfer des callbacks.

En lançant le service test, on réclame le démarrage de browserless et web, l'entrypoint attend leur disponibilité, puis la command lance le test Mocha.

"Et voilà", comme on dit en Amérique, le test fonctionnel fonctionne en local et dans le CI, avec l'outillage nécessaire pour le déboguer. Reste à le décliner pour le lancer sur la prod, et voir comment ça passe avec son proxy applicatif et autres CDN.

Là, le test se contente de lire la page, il faudrait qu'il fasse des trucs pour être plus pertinent, comme cliquer sur un lien ou un bouton, remplir un formulaire.

Bons tests.

Service Conseil et accompagnement docker

Bearstech vous propose ses services Conseil et accompagnement docker

Découvrir ce service

Partager cet article

Flux RSS

flux rss

Partager cet article :