Logo JetBase
  • Accueil
  • Blog
  • Migration des tests Cypress vers Playwright avec Copilot
Bannière

L'essentiel

Une migration de Cypress vers Playwright ne doit pas devenir une réécriture à haut risque. Sur une plateforme de santé, 148 tests E2E ont été déplacés de manière incrémentale tandis que Cypress restait actif dans CI, préservant la couverture des versions tout au long de la transition. GitHub Copilot a réduit le travail de conversion répétitif de 70 à 80 %, mais une migration sécurisée nécessitait encore un examen humain, des configurations de framework isolées et une validation fichier par fichier.

• Construire le prototype Playwright en 1 à 2 jours.
• Exécuter les deux frameworks jusqu'à ce que chaque suite soit stable.
• Migrer les fichiers de support avant les fichiers de test.
• Examiner manuellement les imports, les fixtures, les localisateurs et les assertions.

Lorsque nous avons reçu une demande de migration des tests Cypress vers Playwright, nous nous attendions à un long processus de réécriture ennuyeux.

Surprisingly, avec l'aide de GitHub Copilot, nous avons réussi à lancer la migration de Cypress à Playwright en seulement quelques jours — et à garder notre pipeline CI en cours d'exécution tout le temps sans interrompre aucun processus de test.

Dans cet article, je partagerai notre approche de cette migration, les leçons que nous avons apprises en cours de route et comment l'assistance à la migration de code par l'IA peut réduire considérablement la charge manuelle lors des transitions de cadre.

1

Contexte du Projet

Le projet était une plateforme de santé complexe avec beaucoup de choses en coulisses. Notre configuration de test comprenait :

  • Tests de bout en bout (E2E) et tests d'intégration
  • Une architecture TAF personnalisée avec des configurations, des nettoyages et des créations d'entités
  • Configurations multi-environnements
  • Données dynamiques et logique de navigation approfondie

Au total, nous avions 148 tests E2E fonctionnant sur Cypress — tous fonctionnant correctement, mais l'organisation voulait standardiser les outils QA entre les équipes, ce qui signifiait une chose : migration vers Playwright.

2

Pourquoi utiliser GitHub Copilot pour la Migration ?

Lorsque la demande de migration est arrivée, j'ai vu une opportunité d'expérimenter avec l'automatisation des tests GitHub Copilot. Au lieu de réécrire manuellement des centaines de fichiers de test, je voulais voir jusqu'où nous pourrions pousser l'assistance de l'IA pour automatiser la conversion de syntaxe de Cypress à Playwright.

Et honnêtement, cela a fonctionné bien mieux que prévu.

GitHub Copilot a géré la plupart des traductions répétitives (sélecteurs, commandes, gestion asynchrone, etc.), nous permettant de nous concentrer sur les ajustements d'infrastructure et le perfectionnement.

En 1 à 2 jours, nous avions déjà un prototype fonctionnel du cadre d'automatisation des tests Playwright.

3

Deux Avertissements Clés

Vérifiez toujours le Code Généré par l'IA

Bien que l'assistance à la migration de code par l'IA accélère les choses, vous devez revoir chaque ligne. Les migrations d'infrastructure peuvent facilement introduire des bogues subtils ou des régressions de performance. Pensez à Copilot comme votre pair programmeur, pas comme un pilote automatique.

Maintenez le Ancien Cadre en Fonction jusqu'à la Fin

Ne bloquez jamais les releases ou les régressions pendant la migration. Gardez vos tests Cypress en cours d'exécution sur CI jusqu'à ce que les ensembles correspondants soient entièrement stables dans Playwright. Une fois un ensemble migré et validé, retirez-le de Cypress et passez CI pour l'exécuter dans Playwright.

Ce déploiement progressif garantit zéro temps d'arrêt et une couverture de test continue tout au long du processus.

4

Flux de Travail pour Migrer de Cypress à Playwright

Une fois les bases clairement établies, nous sommes passés à la migration pratique.  
Ci-dessous se trouve le flux de travail qui nous a aidés à exécuter les deux cadres en parallèle, à maintenir la stabilité CI et à commencer à migrer les tests progressivement — sans bloquer les releases en cours.

1. Initialiser Playwright et Créer la Structure de Dossier

La première étape a été d'initialiser Playwright et de créer une structure de dossiers propre et isolée.

Nous voulions que les deux frameworks coexistent dans le même référentiel, afin que nous puissions les exécuter simultanément pendant la transition.

Cette configuration nous a permis de :

  • Migrer progressivement
  • Comparer les résultats et les temps entre Cypress et Playwright
  • Maintenir les pipelines CI actifs pour les deux

Exemple d'initialisation :

Exemple d'initialisation.webp

Voici la structure de dossier proposée que nous avons utilisée pour Playwright :

├── cypress/
│   ├── app/
│   ├── downloads/
│   ├── e2e/
│   ├── fixtures/
│   ├── screenshots/
│   ├── support/
│   └── videos/
├── playwright/
│ 	├── app/
│	│   ├── components/
│	│   ├── fixtures/
│	│   └── pageobjects/
│   ├── constants/
│   ├── helpers/
│   ├── reports/
│   ├── test-results/
│   └── tests/
├── .gitignore
├── package.json
├── playwright.config.ts
├── smoke.config.ts
├── tsconfig.json

2. Configurer des fichiers tsconfig séparés pour chaque framework

L'un des premiers problèmes auxquels nous avons été confrontés était les conflits de TypeScript — les deux frameworks définissent des noms de méthodes similaires (expect, request, etc.), et le partage d'un unique tsconfig.json entraînait des erreurs de compilation.

La solution était simple : diviser les configurations TypeScript. Cette structure garantit que chaque framework initialise ses propres définitions de type et évite les collisions :

├── tsconfig.json
├── tsconfig.cypress.json
├── tsconfig.playwright.json

tsconfig.json principal
Ajoutez l'option composite pour prendre en charge les références de projet.

tsconfig.json

{
  "compilerOptions": {
    "composite": true
  }
}

tsconfig.cypress.json

{
  "extends": ".‌/tsconfig.json",
  "compilerOptions": {
    "types": ["cypress", "@testing-library/cypress", "node"],
    "isolatedModules": false
  },
  "include": ["cypress/**/*.ts"]
}

tsconfig.playwright.json

{
  "extends": ".‌/tsconfig.json",
  "compilerOptions": {
    "types": ["node", "@playwright/test"]
  },
  "include": ["playwright/**/*.ts", "playwright.config.ts"]
}

Avec cette séparation en place, les deux frameworks pouvaient coexister paisiblement dans un même répertoire — plus de conflits de compilateur, et aucun risque d'initialiser accidentellement des méthodes partagées deux fois.

3.

Créer un prompt pour automatiser la migration avec GitHub Copilot

Une fois Playwright initialisé et le projet structuré, il était temps de laisser GitHub Copilot s'occuper du travail lourd.

Pour ce faire, nous avons créé un prompt personnalisé qui définit comment Copilot doit se comporter lors de la réécriture des tests de Cypress à Playwright. Le prompt indique à l'agent quoi faire, comment le faire et quoi ignorer — offrant des résultats cohérents à travers toutes les migrations.

Comment ajouter le prompt

Dans votre dépôt GitHub, ouvrez l'icône d'engrenage ⚙️ dans Copilot Chat et créez un nouveau prompt.  
Le fichier sera enregistré automatiquement sous : ./github/prompts/

Vous pouvez l'appeler quelque chose comme migrate_tests.md.

Exemple de prompt :

---
mode: agent
---
Vous êtes un générateur de tests Playwright, un expert en automatisation de navigateurs et tests de bout en bout.
Votre spécialité est de créer des tests Playwright robustes et fiables qui simulent précisément les interactions utilisateur et valident le comportement de l'application.
Votre tâche est d'aider à migrer les tests Cypress existants vers des tests Playwright.
Les tests Cypress, les objets de page, les composants et les fichiers d'assistance sont fournis en entrée, et vous devez générer un code de test Playwright équivalent.
Sortie TOUT le code migré dans le chat.
Lors de la génération du code de test Playwright ou de tout objet de page, assurez-vous que :
1. La structure du test suit la même structure que les tests Cypress.
2. Créez un fixture global pour la configuration et le démontage et réutilisez-le dans les tests.
3. Toutes les interactions utilisateur (clics, saisie, navigation) sont traduites avec précision en syntaxe Playwright dans les objets de page et les fichiers de test.
4. Les assertions dans Cypress sont converties en assertions Playwright équivalentes.
5. Ignorez les parties d'espionnage et de stubbing réseau des tests Cypress.
6. Commentez toutes les méthodes avec des pauses (par ex., cy.wait) dans le code Playwright.
7. N'utilisez pas de méthodes get dans les objets de page ; utilisez des méthodes directes à la place `backbackItem = () => this.page.locator('[id="item_4_title_link"]');`

Pourquoi cela aide

Ce type de prompt structuré permet à GitHub Copilot de se comporter plus comme un assistant de migration spécialisé, et non comme un générateur de code généraliste.

Avec le bon contexte et les bonnes règles, Copilot peut automatiquement :

  • Réécrire de larges portions de tests Cypress en syntaxe Playwright
  • Maintenir la cohérence de la structure des dossiers et des tests 
  • Réduire le temps de conversion manuelle de 70 à 80 %

Essentiellement, vous créez votre propre chaîne d'outils de migration AI — adaptée à la structure et aux conventions de votre projet.

4. Sélectionnez le mode agent et exécutez la migration étape par étape

Une fois le prompt prêt, l'étape suivante était de réellement exécuter la migration avec GitHub Copilot en mode agent. À cette phase, nous laissons le modèle AI traiter chaque fichier — objets de page, composants, aides, et enfin les tests — un par un.

Pour cette tâche, nous avons utilisé le modèle GPT-4.1, qui fournit les transformations de code les plus cohérentes et conscientes du contexte.

Comment commencer la migration

1. Ouvrez Copilot Chat dans VS Code

2. Utilisez / pour sélectionner le fichier de prompt que vous avez créé précédemment

3. Utilisez # pour sélectionner un fichier spécifique (par exemple, un test Cypress ou un objet de page) que vous souhaitez migrer

Copilot appliquera maintenant votre invite de migration et générera une version compatible avec Playwright du fichier directement dans le chat.

Comment commencer la migration.webpExemple de migration de l'objet de page inventoryPage

import { ItemComponent } from "..‌/components/item.component";
import Common from ".‌/common";
class InventoryPage extends Common {
  item = new ItemComponent();
  backbackItem = () => cy.get("#item_4_title_link");
  backbackAddItemButton = () => cy.getByTestId("add-to-cart-sauce-labs-backpack");
  bikeLightsAddItemButton = () => cy.getByTestId("add-to-cart-sauce-labs-bike-light");
  backbackRemoveItemButton = () => cy.getByTestId("remove-sauce-labs-backpack");
  shoppingCartLogo = () => cy.get("#shopping_cart_container");
  clickBackbackAddItemButton = () => this.backbackAddItemButton().click();
  clickBikeLightsAddItemButton = () => this.bikeLightsAddItemButton().click();
  clickBackbackRemoveItemButton = () => this.backbackRemoveItemButton().click();
  assertCartLogoItems = (itemsNum: number) => this.shoppingCartLogo().should("have.text", itemsNum);
}
export default new InventoryPage();

 

import { Page, Locator, expect } from "@playwright/test";
import Common from ".‌/common";
class InventoryPage extends Common {
  constructor(page: Page) {
    super(page);
    this.item = new ItemComponent(page);
  }
  
  // Locators
  backbackItem(): Locator {
    return this.page.locator("#item_4_title_link");
  }
  backbackAddItemButton(): Locator {
    return this.page.getByTestId("add-to-cart-sauce-labs-backpack");
  }
  bikeLightsAddItemButton(): Locator {
    return this.page.getByTestId("add-to-cart-sauce-labs-bike-light");
  }
  backbackRemoveItemButton(): Locator {
    return this.page.getByTestId("remove-sauce-labs-backpack");
  }
  shoppingCartLogo(): Locator {
    return this.page.locator("#shopping_cart_container");
  }
  // Actions
  async clickBackbackAddItemButton(): Promise<void> {
    await this.backbackAddItemButton().click();
  }
  async clickBikeLightsAddItemButton(): Promise<void> {
    await this.bikeLightsAddItemButton().

Ajuster le comportement de l'agent

Ne vous inquiétez pas si la première sortie n'est pas parfaite. D'après notre expérience, l'agent d'IA obtient généralement 60 à 70 % du code correct lors de la première tentative. La clé est de garder le contexte de la conversation actif — continuez à affiner le même fil de discussion en demandant des corrections ou des ajustements. En faisant cela, Copilot commence à apprendre vos schémas de projet et produit un code plus précis et réutilisable.

Essentiellement, plus vous effectuez d'itérations dans le même chat, meilleure sera la qualité de la migration.

Ordre de migration : fichiers d'abord, puis tests

Pour garder les dépendances cohérentes et éviter de manquer des références, suivez cet ordre :

1. Générez d'abord les fichiers non-test :

  • Objets de page
  • Composants
  • Fichiers d'aide
  • Constantes

2. Une fois tous les fichiers de support générés et vérifiés, ajoutez le #app dans le contexte de chat, puis migrez les fichiers de test eux-mêmes.

Étape de vérification

Lorsqu'un test Playwright est généré :

1. Examinez le code — confirmez que les locateurs de page, les étapes de test et les assertions sont corrects.

2. Exécutez le test en utilisant votre CLI Playwright pour vous assurer qu'il s'exécute correctement.

3. Corrigez les légers désaccords de syntaxe ou de fixture si Copilot a mal compris une commande Cypress.

En vérifiant après chaque fichier, vous maintenez la migration stable et incrémentielle, évitant ainsi un débogage à grande échelle plus tard.

Exemple de test inventoryPage migré qui réussit :

```html backbackItem().should("have.text", itemsNames.backpackItemName); inventoryPage.clickBackbackAddItemButton(); inventoryPage.assertCartLogoItems(1); inventoryPage.clickBikeLightsAddItemButton(); inventoryPage.assertCartLogoItems(2); }); });

 

import { test, expect } from "..‌/fixtures/test.fixture";
import { itemsNames } from "../..‌/constants/data.json";
// InventoryPage tests migrated from Cypress to Playwright
test.describe("InventoryPage tests", () => {
  test.beforeEach(async ({ pageManager }) => {
    await pageManager.loginPage.loginWithValidData();
  });
  test("The user should add item to the cart", async ({ pageManager }) => {
    await expect(
    pageManager.inventoryPage.item.itemByName(itemsNames.bikeLight)).toHaveText(itemsNames.bikeLight);
    await pageManager.inventoryPage.item.addToCartByName(itemsNames.bikeLight);
    await pageManager.inventoryPage.assertCartLogoItems(1);
  });
  test("The user should remove item from the cart", async ({ pageManager }) => {
    await expect(
      pageManager.inventoryPage.backbackItem()).toHaveText(itemsNames.backpackItemName);
    await pageManager.inventoryPage.clickBackbackAddItemButton();
    await pageManager.inventoryPage.assertCartLogoItems(1);
    await pageManager.inventoryPage.clickBackbackRemoveItemButton();
    await expect(pageManager.inventoryPage.shoppingCartLogo()).not.toHaveText(/\d/); // Should not have any number text
  });
  test("The user should add multiple items to the cart", async ({ pageManager }) => {
    await expect(pageManager.inventoryPage.backbackItem()).toHaveText(itemsNames.backpackItemName);
    await pageManager.inventoryPage.clickBackbackAddItemButton();
    await pageManager.inventoryPage.assertCartLogoItems(1);
    await pageManager.inventoryPage.clickBikeLightsAddItemButton();
    await pageManager.inventoryPage.assertCartLogoItems(2);
  });
});

5. Structure finale du dépôt après migration

Une fois la migration terminée, notre dépôt a atteint un état stable à double cadre — fonctionnant pleinement avec Cypress et Playwright côte à côte. Cette structure nous a permis de :

  • Dépérir progressivement les suites de tests Cypress au fur et à mesure qu'elles étaient remplacées
  • Maintenir les pipelines CI/CD opérationnels pour les deux frameworks
  • Conserver une architecture propre et modulaire

Ci-dessous la structure finale après avoir complété le flux de migration.

Structure finale des dossiers

├── .env
├── .gitignore
├── readme.md
├── package.json
├── playwright.config.ts
├── smoke.config.ts
├── tsconfig.cypress.json
├── tsconfig.playwright.json
├── tsconfig.json
├── .```
github/
│   ├── prompts/
│   └── workflows/
├── cypress/
│   ├── app/
│   ├── downloads/
│   ├── e2e/
│   ├── fixtures/
│   ├── screenshots/
│   ├── support/
│   └── videos/
├── playwright/
│   ├── app/
│   ├── constants/
│   ├── helpers/
│   ├── reports/
│   ├── test-results/
│   └── tests/

Notes sur la Structure

  • .github/prompts/ — contient vos invites de migration Copilot. Garder celles-ci versionnées vous permet de les mettre à jour ou de les réutiliser pour de futures migrations ou refontes de framework.
  • .github/workflows/ — contient vos définitions CI/CD. Vous pouvez exécuter à la fois des travaux Playwright et Cypress en parallèle jusqu'à la dépréciation complète de l'ancien framework.
  • playwright/ dossier — agit désormais comme la source principale d'automatisation à l'avenir. Il reflète la structure de l'implémentation précédente de Cypress pour faciliter l'intégration et garantir la cohérence.
  • tsconfig.playwright.json et tsconfig.cypress.json — restent séparés pour une isolation complète des types, évitant les conflits lors des constructions.

Cette structure a non seulement soutenu une transition fluide, mais a également positionné le projet pour une évolutivité future, la flexibilité CI et une propriété modulaire des tests à travers les équipes.

 
Planifier une migration de Cypress à Playwright ?

Déplacez votre suite de tests sans perturber les sorties ni perdre de couverture. Nos ingénieurs QA peuvent vous aider à planifier la migration, adapter votre architecture d'automatisation et maintenir les deux frameworks stables pendant la transition.

5

Conseils pratiques & leçons apprises

Après avoir migré près de 150 tests avec Copilot et Playwright, voici quelques leçons clés et conseils concrets qui ont rendu le processus plus fluide (et nous ont évité quelques maux de tête).

Conseils généraux liés à l'IA

  • L'IA ment — souvent de manière convaincante.  

Vérifiez toujours chaque ligne de code que l'IA génère. Ne lui faites jamais confiance aveuglément, surtout lors des migrations d'infrastructure.

  • Respectez des conventions de nommage cohérentes.

Gardez des noms de variables et de méthodes identiques à travers les frameworks — cela aide l'Agent IA à migrer le code plus précisément et facilite leur recherche et leur importation ultérieure.

Conseils généraux liés à l'IA.webp

  • Reconstruisez les imports manuellement.

Copilot a tendance à déranger les chemins d'importation. Il est souvent plus rapide de les supprimer et de les réimporter manuellement, ou de configurer des imports globaux comme : import x from "playwright/foo/bar";

  • Réutilisez le même chat pour toutes les migrations. ```

Respectez un seul fil de chat Copilot — cela crée un contexte et « se souvient » de vos conventions de projet, entraînant de meilleurs résultats.

  • Décomposez les tâches de migration.  

Générez 1 à 2 fichiers à la fois. Des tâches plus petites aboutissent à des résultats plus précis et facilitent la validation manuelle.

Conseils spécifiques à Playwright

  • Ne créez jamais plusieurs instances du même objet de page sans nécessité.

Le faire peut entraîner un état incohérent ou des sélecteurs cassés lors de la navigation entre les pages. La solution ? Implémentez un gestionnaire de pages qui garde tous les objets de page accessibles via une seule instance.

Voici un exemple de configuration minimale :

// login.page.ts
class LoginPage extends Common {
  async clickLoginButton(): Promise<void> {
    await this.loginButton().click();
  }
}
export default LoginPage;
//-----------------------------------------------------------
//PageManager.ts
export class PageManager {
  readonly loginPage: LoginPage;
  constructor(page: Page) {
    this.loginPage = new LoginPage(page);
  }
}
//-----------------------------------------------------------
//test.fixture.ts
export const test = base.extend<{
  pageManager: PageManager;
}>({
  pageManager: async ({ page }, use) => {
    const manager = new PageManager(page);
    await use(manager);
  },
});
export { expect };
//-----------------------------------------------------------
//userLogin.spec.ts
  test("L'utilisateur doit se connecter avec des données valides", async ({ pageManager }) => {
    await pageManager.loginPage.clickLoginButton();
  });

Autres conseils techniques

  • Supprimez tous les préfixes « get » des locateurs générés par l'agent AI — utilisez plutôt des méthodes de locateur directes.
  • N'oubliez pas de configurer dotenv pour les variables d'environnement et les identifiants.
  • Personnalisez votre configuration Playwright pour enregistrer tous les rapports sous le dossier Playwright, afin que la racine de votre projet reste propre :
reporter: [["html", { open: "never", outputFolder: ".‌/playwright/reports/" }]],
  outputDir: ".‌/playwright/test-results",
6

Épilogue

Je n'ai pas inclus la configuration ESLint ici car elle varie d'un projet à l'autre.  
La seule recommandation universelle que je peux faire est d'installer le plugin ESLint Playwright pour un meilleur respect des règles : eslint-plugin-playwright.

Si vous souhaitez explorer un exemple complet de cette migration — y compris des fichiers de prompt, des tsconfigs, et une configuration CI — vous pouvez consulter le dépôt complet ici : Exemple de dépôt.

 
Prêt à moderniser votre automatisation de tests ?

Que vous migriez de Cypress, reconstruisiez une suite de tests instable ou amélioriez votre automatisation QA, JetBase peut vous aider à effectuer la transition avec moins de travail manuel et un risque de livraison réduit.

Commentaires

Connectez-vous pour laisser un commentaire
Continuer avec GoogleContinuer avec Google
Moderne

Nos Cas

L'innovation ne concerne pas seulement les idées - il s'agit de l'exécution, de transformer la vision en réalité et de créer des solutions qui ont vraiment un impact. Voyez ce que nous avons construit et comment cela fonctionne :

  • Soins de santé
  • Médias et Divertissement
  • eCommerce
  • Amazon Web Services
  • Optimisation des coûts cloud
  • Application sans serveur
  • Vente au détail
  • Santé - Bannière
    • 100 %Conforme à la HIPAA
    • 99,99% de disponibilitéFiabilité Maximale
  • Santé - Bannière
    • 10 000+Patients soutenant
    • Engagement 30%+UX adaptatif

Derniers Articles