Tests end-to-end avec Playwright

Cas d'usage : tester son module Magento 2

Introduction

Tester un module Magento 2 de bout en bout avec un outil comme Playwright présente plusieurs avantages :

  • Validation de l'expérience utilisateur (UX) : Les tests de bout en bout permettent de s'assurer que l'expérience utilisateur de votre site web Magento 2 fonctionne correctement. Playwright peut automatiser des actions telles que la navigation, le remplissage de formulaires, la sélection de produits, le paiement, etc., pour vérifier que tout se passe comme prévu du point de vue de l'utilisateur.
  • Identification des problèmes de fonctionnalité : En testant l'ensemble du flux utilisateur, vous pouvez identifier les problèmes de fonctionnalité qui pourraient survenir lorsque les différentes parties de votre module Magento 2 interagissent entre elles. Cela permet de détecter les bugs et de les corriger avant qu'ils n'affectent les clients.
  • Assurance qualité (QA) : Les tests de bout en bout font partie intégrante de l'assurance qualité (QA) pour garantir que votre module Magento 2 répond aux normes de qualité et fonctionne correctement. Cela peut aider à éviter les retours clients, les problèmes de réputation et les pertes de ventes.
  • Réduction des erreurs humaines : L'automatisation des tests avec Playwright permet de réduire les erreurs humaines potentielles lors de la vérification manuelle de chaque fonctionnalité. Les tests automatisés sont également reproductibles et peuvent être exécutés à tout moment.
  • Gain de temps : Les tests automatisés permettent de gagner du temps par rapport à la vérification manuelle, surtout lorsque vous devez effectuer des tests de regression à chaque mise à jour de votre module. Cela permet d'accélérer le processus de développement.
  • Support de différents navigateurs : Playwright prend en charge plusieurs navigateurs, ce qui vous permet de tester votre module Magento 2 sur différentes plateformes et de vous assurer qu'il fonctionne correctement pour tous les utilisateurs, quelle que soit leur configuration.
  • Intégration dans un processus de CI/CD : Vous pouvez intégrer les tests de bout en bout avec Playwright dans votre processus de livraison continue (CI/CD) pour automatiser la validation de votre module à chaque nouvelle version ou mise à jour, assurant ainsi une meilleure stabilité du produit final.

Expérience personnelle

Merci ChatGPT, je n'aurais pas dit mieux. Pour la suite, je vais essayer d'écrire moi-même, pour rendre le sujet un peu plus humain, même s'il faut bien avouer que les tests automatisés, c'est plutôt une affaire de robots.

Je souhaite partager ici mon expérience et donner un aperçu de ma façon d'utiliser Playwright pour tester des modules Magento 2.

Bien sûr, la mise en place de tels tests prend du temps, surtout pour le premier module testé. Mais une fois qu'on l'a fait pour un module, c'est souvent assez facilement transposable et la satisfaction de savoir que son module fonctionne (au moins dans la limite des tests qu'on a écrits) mérite bien, à mon avis, de prendre ce temps.

En résumé, les étapes à répéter sont quasiment toujours les mêmes :

  • étape 1 : Installer Magento 2
  • étape 2 : Activer le module
  • étape 3 : Tester le module de bout en bout :
    • étape 3-1 : Se rendre dans le back office pour activer la ou les fonctionnalités apportées par le module
    • étape 3-2 : Exécuter différentes actions en front ou backend et s'assurer que le résultat est conforme au résultat attendu
    • Refaire les étapes 3-1 et étapes 3-2 en modifiant d'éventuelles configurations, aussi souvent que nécessaire.

Éventuellement, on pourra refaire étapes 1,2 et 3 en modifiant certains paramètres de l'environnement de test: versions de PHP, Nginx, Apache, Varnish, etc.

Ce n'est pas le but premier de cet article mais, comme toutes les étapes sont scriptables et que Playwright est utilisable en mode "headless", ces tests pourront faire l'objet d'une automatisation CI/CD. Dans la conclusion, vous trouverez un lien vers une de mes actions GitHub à titre d'exemple.

Ce qui nous intéresse ici est surtout l'étape 3 :

Tester un module avec Playwright

Installation de Playwright

Pour installer Playwright, lire la documentation de Playwright est certainement la meilleure chose à faire.

Personnellement, pour le premier module testé, j'ai crée un dossier Test/EndToEnd dans lequel j'ai lancé la commande :

npm init playwright@latest

Avec cette commande, les navigateurs nécessaires sont téléchargés et les fichiers suivants sont crées :

playwright.config.ts
package.json
package-lock.json
tests/
    example.spec.ts
tests-examples/
    demo-todo-app.spec.ts

Une fois que c'est fait, on peut commencer à s'amuser en lançant :

  • les tests en mode "headless"
npx playwright test
  • les tests en mode "headed"
npx playwright test --headed
npx playwright test --ui

Le fichier playwright.config.ts est à mon avis le plus important et on peut trouver un aperçu des paramétrages possibles dans la documentation.

Pour la mise en place dans d'autres modules, je me contente souvent de récupérer ce fichier de configuration que j'ai modifié selon mes besoins, le package.json et quelques autres fichiers mutualisables puis de lancer un yarn install dans le dossier.

Écrire un test

Comme l'indique la documentation , un test est uniquement l’enchaînement des deux opérations suivantes :

  • exécuter une action : visite une page, cliquer sur un bouton, remplir un formulaire, etc.
  • valider une assertion : vérifier qu'un contenu est présent sur la page, vérifier qu'une url contient le bon paramètre, etc.

Pour faciliter l'écriture des actions, Playwright dispose d'une commande codegen très pratique :

npx playwright codegen

Avec cette commande, un navigateur s'ouvre et chacune de vos actions est transcrite dans une fenêtre "Playwright Inspector". Il ne vous reste plus qu'à copier-coller tout ça pour que votre test réalise exactement les mêmes actions.

Par exemple, la capture d'écran ci-dessous montre l’enchaînement suivant :

Visite de la page d'accueil → Visite d'une page catégorie → Visite d'une page produit → Ajout au panier de 2 produits

Codegen

Pour avoir une idée des possibilité d'assertions: https://playwright.dev/docs/test-assertions.

Organisation du code : Page Object Model et Fixtures

Ce que je viens de décrire plus haut suffit largement pour être capable de tester son module. Mais si on souhaite organiser son code pour qu'il soit plus rapidement réutilisable, on pourra intégrer les concepts de Page Object Model et de Fixtures.

L'idée de base du Page Object Model est de se dire qu'à chaque page visitable doit correspondre un objet, avec quelques propriétés et méthodes nécessaires aux tests.

Concernant le principe de Fixtures, il a pour but de maîtriser l'environnement de départ (jeu de données, configuration, etc.) de chaque test ou groupe de tests.

Si vous êtes vraiment motivés, vous pourriez aboutir à un code qui ressemble à celui de ce repo Cypress avec des jolis dossiers de fixtures et de pages-objects, et leurs déclinaisons éventuelles par thèmes (Luma, Hyva, etc.). Désolé, cet exemple est basé sur Cypress, le "concurrent" de Playwright mais le principe reste le même et je n'ai pas eu le temps de mettre en place une arborescence aussi propre pour le moment.

Je mettrais quelques liens vers mes projets en cours et vous pourrez regarder mes dossiers de fixtures et de page-objects, beaucoup moins fournis mais cohérents avec mes besoins.

À titre d'exemple, la page de login du back office est une excellente candidate pour devenir une "page-objet". En effet, on est obligatoirement amener à s'y rendre si on souhaite configurer son module. Ainsi, j'ai crée un objet adminLoginPage avec les méthodes de bases dont les noms et contenus seront, j'espère, assez explicites pour ne pas avoir à les décrire ici :

  • navigateTo
  • login
  • logout

Dans le même esprit, j'ai crée des objets pour la page d'accueil, pour une page produit, pour une page catégorie, pour le tunnel de paiement et pour toutes autres pages qui peuvent me servir dans mes tests, selon les modules.

Comme promis, voici ce que ça donne pour un de mes modules qui n'a besoin que du thème Luma pour une page catégorie et de quelques pages du back office (login, cache, configuration et édition d'une page catégorie) :

Gestion de l'authentification

Comme tous mes tests nécessitent de se connecter au back office, j'ai mis en place une des stratégies proposées par Playwright pour stocker et réutiliser les cookies qui gèrent l'authentification.

Chaque test étant exécuté dans un contexte isolé (équivalent d'un nouveau navigateur en navigation privée), cette étape est nécessaire pour ne pas devoir se re-connecter avant chaque nouveau test du projet.

Pour cela, on modifie le fichier playwright.config.ts et on fait on fait dépendre tout nos groupes de tests (appelés projets) d'un projet "setup" dans lequel :

  • on visite la page de connexion adminLoginPage.
  • On saisit les login/mot de passe de notre utilisateur de test.
  • On se connecte et on sauvegarde l'état d’authentification dans un fichier json.

Ainsi, tout groupe de test sera précédé par la connexion à l'admin :


Cas d'usage : Okaeli_RoundPricesCut

Le module Okaeli_RoundPricesCut a pour but d'afficher les prix ronds sans les décimales.

Par défaut, un prix de 15,00€ est affiché 15,00€. Ce module permet d'afficher 15€ : rien de révolutionnaire mais c'est une fonctionnalité qu'on m'a très souvent demandée lorsque je travaillais en agence web. Alors j'en ai fait un module.

Bien que simples, les tests manuels sont fastidieux et rébarbatifs : on doit s'assurer que ça fonctionne sur les pages catégories, sur les pages produits, pour les options de prix des produits configurables, lors du processus d'achat, etc.

Je ne détaillerai ici que les tests sur les produits configurables et le test du processus d'achat car ils donnent à mon avis une bonne idée de l'ensemble.

Pré-requis

Afin d'avoir toujours le même jeu de test, j'installe certaines données de test Magento :

bin/magento setup:performance:generate-fixtures setup/performance-toolkit/profiles/ce/small.xml

Test de la page du produit configurable

Le test consiste à se rendre sur la page d'un produit configurable pour tester que tout se déroule comme prévu:

  • si la fonctionnalité est activée, les prix ronds doivent s'afficher sans décimales
  • si la fonctionnalité est désactivée, les prix ronds doivent s'afficher avec les décimales

Dans ce but, on peut créer un objet ConfigurableProductOnePage qui représente la page d'un produit configurable:

import { expect, Page } from "@playwright/test";

export default class ConfigurableProductOnePage {
    page: Page;
    url: string;

    constructor(page: Page) {
        this.url = "/configurable-product-1.html";
        this.page = page;
    }

    public async navigateTo(check = true) {
        await this.page.goto(this.url);
        if (check) {
            await expect(this.page).toHaveTitle(/Configurable Product 1/);
        }
    }
}

En pratique, le test est composé de plusieurs sous tests:

  • Préparation du test

    • on se connecte au back office (setup vu plus haut)
  • Test 1 : on s'assure qu'on peut paramétrer les configurations du module par défaut

    • on se rend sur la page de configuration du module (CatalogPrice dans ce cas)
    • on active la fonctionnalité sur le front
    • on vide le cache
Test 1: activation de la fonctionnalité

Au niveau du code, ça ressemble à ça :

test("can set default config", async ({
    adminOkaeliRoundPricesConfigPage,
    adminCachePage,
  }) => {
    await adminOkaeliRoundPricesConfigPage.setDefaultConfig();
    await adminCachePage.navigateTo();
    await adminCachePage.flushMagentoCache();
  });
  • Test 2 : Visite de la page produit avec la fonctionnalité activée
    • on se rend sur la page produit avec un prix de base rond
    • on vérifie que l'affichage du prix est cohérent (pas de décimales)
    • on change l'option (option prix rond)
    • on vérifie que l'affichage du prix est cohérent (pas de décimales)
    • on change l'option (option prix non rond)
    • on vérifie que l'affichage du prix est cohérent (les décimales sont présentes)
Test 2 : Vérification de l'affichage des prix

Le code associé à ce test est le suivant :

test("can see rounded prices on configurable product", async ({
  configurableProductOnePage,
  page,
}) => {
    await configurableProductOnePage.navigateTo();
    await expect(page.locator(".product-info-price")).toHaveText(/\$1/);
    await expect(page.locator(".product-info-price")).not.toHaveText(/\$1.00/);
    await page.locator("select").selectOption({ index: 1 });
    await expect(page.locator(".product-info-price")).toHaveText(/\$5/);
    await expect(page.locator(".product-info-price")).not.toHaveText(/\$5.00/);
    await page.locator("select").selectOption({ index: 8 });
    await expect(page.locator(".product-info-price")).toHaveText(/\$9.99/);
});
  • Test 3 : Visite de la page produit avec la fonctionnalité désactivée
    • on se rend sur la page de configuration du module
    • on désactive la fonctionnalité sur le front
    • on vide le cache
    • on refait les mêmes tests que le Test 2 en s'attendant à des résultats différents
Test 3 : Vérification de l'affichage des prix lorsque la fonctionnalité est désactivée

Comme d'habitude, voici le code associé:

test("can disable rounded prices on configurable product", async ({
  adminCachePage,
  adminOkaeliRoundPricesConfigPage,
  configurableProductOnePage,
  page,
}) => {
    await adminOkaeliRoundPricesConfigPage.disableFront();
    await adminCachePage.navigateTo();
    await adminCachePage.flushMagentoCache();
    await configurableProductOnePage.navigateTo();
    await expect(page.locator(".product-info-price")).toHaveText(/\$1.00/);
    await page.locator("select").selectOption({ index: 1 });
    await expect(page.locator(".product-info-price")).toHaveText(/\$5.00/);
    await page.locator("select").selectOption({ index: 8 });
    await expect(page.locator(".product-info-price")).toHaveText(/\$9.99/);
});

Si des erreurs sont détectées, on pourra éventuellement consulter un rapport en lançant :

npx playwright show-report

Test du processus d'achat

Pour voir un test un peu plus complet, je terminerai ici avec le test de l'affichage des prix lors d'un processus d'achat.

Comme pour le test de la page produit, il y a une étape de préparation, un test de configuration, puis deux tests du parcours d'achat : un avec la fonctionnalité activée et un avec la fonctionnalité désactivée.

Je ne présente ici rapidement que le test avec la fonctionnalité activée :

  • on se rend sur la page produit simple
  • on l'ajoute au panier
  • on vérifie les prix dans le mini panier
  • on va au tunnel de paiement ("proceed to checkout")
  • on vérifie que les prix sont bien affichés
  • on remplit les infos de livraison
  • On passe à l'étape suivante (paiement)
  • On vérifie que les prix sont bien affichés : prix du produit, frais de port, sous-total, total)

N.B : La durée entre chaque action a été volontairement ralenti ici pour qu'on puisse comprendre un peu ce qui se passe. En réalité, le test est bien plus rapide.

Test du parcours d'achat

Conclusion

Cette présentation ne fait que survoler l'étendue des possibilités de Playwright. J'espère quand même qu'elle vous sera utile si jamais vous souhaitez donner une chance à cet outil.

Comme annoncé plus haut, vous trouverez ici un exemple d'action GitHub dans lequel j'installe un module Magento 2 et lance les tests Playwright.

OKAELI