Maison > interface Web > js tutoriel > Test du dramaturge et du navigateur Chrome dans Heroku

Test du dramaturge et du navigateur Chrome dans Heroku

Mary-Kate Olsen
Libérer: 2024-12-06 10:35:12
original
239 Les gens l'ont consulté

J'ai toujours aimé regarder mes tests unitaires s'exécuter (et réussir). Ils sont rapides et réussir les tests me donne l’assurance que mes pièces individuelles se comportent comme elles sont censées le faire. À l’inverse, j’ai souvent eu du mal à prioriser les tests de bout en bout pour le navigateur, car leur écriture et leur exécution étaient extrêmement lentes.

Heureusement, les outils de test de bout en bout dans le navigateur se sont améliorés et plus rapides au fil des années. Et avec une configuration de navigateur sans tête, je peux exécuter mes tests de navigateur dans le cadre de mon CI.

Récemment, je suis tombé sur cet article de blog Heroku parlant de l'automatisation des tests dans le navigateur avec Chrome sans tête dans Heroku CI. Heroku dispose d'un buildpack qui installe Chrome sans tête, que vous pouvez appeler pour vos tests dans le pipeline CI.

L'exemple de configuration tiré de l'article de blog était une application React testée avec Puppeteer et Jest. C'est un bon début … mais que se passe-t-il si j'utilise Playwright au lieu de Puppeteer ? Est-ce possible ?

J'ai décidé d'enquêter. Il s'avère que — oui, vous pouvez aussi le faire avec Playwright ! J'ai donc capturé les étapes dont vous auriez besoin pour exécuter les tests Playwright sur le navigateur Chrome sans tête utilisé dans Heroku CI. Dans cet article, je vais vous guider à travers les étapes de configuration.

Un mot rapide sur l'automatisation du navigateur pour les tests de bout en bout

Les tests de bout en bout capturent la manière dont les utilisateurs interagissent réellement avec votre application dans un navigateur, validant ainsi des flux de travail complets. Playwright rend ce processus assez transparent grâce aux tests dans Chrome, Firefox et Safari. Bien sûr, exécuter une série complète de tests de navigateur dans CI est assez lourd, c'est pourquoi le mode sans tête est utile.

Le buildpack Chrome for Testing de Heroku installe Chrome sur une application Heroku, afin que vous puissiez exécuter vos tests Playwright dans Heroku CI avec une configuration vraiment légère.

Introduction à l'application de test

Puisque je venais d'essayer cela, j'ai créé le dépôt GitHub qui était initialement référencé dans le billet de blog Heroku. L'application était une simple application React avec un lien, une saisie de texte et un bouton de soumission. Il y a eu trois tests :

  1. Vérifiez que le lien fonctionne et redirige vers le bon emplacement.

  2. Vérifiez que la saisie de texte affiche correctement la saisie de l'utilisateur.

  3. Vérifiez que la soumission du formulaire met à jour le texte affiché sur la page.

Assez simple. Maintenant, j'avais juste besoin de changer le code pour utiliser Playwright au lieu de Puppeteer et Jest. Oh, et je voulais aussi utiliser pnpm au lieu de npm. Voici un lien vers mon dépôt GitHub forké.

Modifier le code pour utiliser Playwright

Passons en revue les étapes que j'ai suivies pour modifier le code. J'ai commencé avec mon dépôt forké, identique au dépôt heroku-examples.

Utiliser NPPM

Je voulais utiliser pnpm au lieu de npm. (Préférence personnelle.) Alors, voici ce que j’ai fait en premier :

~/project$ corepack enable pnpm


~/project$ corepack use pnpm@latest

Installing pnpm@9.12.3 in the project…
…
Progress: resolved 1444, reused 1441, downloaded 2, added 1444, done
…
Done in 14.4s

~/project$ rm package-lock.json


~/project$ pnpm install # just to show everything's good


Lockfile is up to date, resolution step is skipped
Already up to date
Done in 1.3s
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ajouter un dramaturge au projet

Ensuite, j'ai supprimé Puppeteer et Jest, et j'ai ajouté Playwright.

~/project$ pnpm remove \
           babel-jest jest jest-puppeteer @testing-library/jest-dom

~/project$ $ pnpm create playwright
Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Do you want to use TypeScript or JavaScript? · JavaScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · false
✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · false
✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo pnpm exec playwright install-deps')? (y/N) · false

Installing Playwright Test (pnpm add --save-dev @playwright/test)…
…
Installing Types (pnpm add --save-dev @types/node)…
…
Done in 2.7s
Writing playwright.config.js.
Writing tests/example.spec.js.
Writing tests-examples/demo-todo-app.spec.js.
Writing package.json.
Copier après la connexion
Copier après la connexion
Copier après la connexion

J'ai également supprimé la section de configuration Jest de package.json.

Configurer Playwright pour utiliser Chromium uniquement

Vous pouvez exécuter vos tests Playwright dans Chrome, Firefox et Safari. Comme je me concentrais sur Chrome, j'ai supprimé les autres navigateurs de la section projets du fichier playwright.config.js généré :

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },

//    {
//      name: 'firefox',
//      use: { ...devices['Desktop Firefox'] },
//    },
//
//    {
//      name: 'webkit',
//      use: { ...devices['Desktop Safari'] },
//    },


  ],
…
Copier après la connexion
Copier après la connexion
Copier après la connexion

Échangez le code de test Puppeteer contre le code de test Playwright

Le code original avait un fichier de test Puppeteer à l'adresse src/tests/puppeteer.test.js. J'ai déplacé ce fichier vers tests/playwright.spec.js. Ensuite, j'ai mis à jour le test pour utiliser les conventions de Playwright, qui se sont mappées assez clairement. Le nouveau fichier de test ressemblait à ceci :

const ROOT_URL = 'http://localhost:8080';
const { test, expect } = require('@playwright/test');

const inputSelector = 'input[name="name"]';
const submitButtonSelector = 'button[type="submit"]';
const greetingSelector = 'h5#greeting';
const name = 'John Doe';

test.beforeEach(async ({ page }) => {
  await page.goto(ROOT_URL);
});

test.describe('Playwright link', () => {
  test('should navigate to Playwright documentation page', async ({ page }) => {
    await page.click('a[href="https://playwright.dev/"]');
    await expect(page.title()).resolves.toMatch('| Playwright');
  });
});

test.describe('Text input', () => {
  test('should display the entered text in the text input', async ({ page }) => {
    await page.fill(inputSelector, name);

    // Verify the input value
    const inputValue = await page.inputValue(inputSelector);
    expect(inputValue).toBe(name);
  });
});

test.describe('Form submission', () => {
  test('should display the "Hello, X" message after form submission', async ({ page }) => {
    const expectedGreeting = `Hello, ${name}.`;
    await page.fill(inputSelector, name);
    await page.click(submitButtonSelector);

    await page.waitForSelector(greetingSelector);
    const greetingText = await page.textContent(greetingSelector);
    expect(greetingText).toBe(expectedGreeting);
  });
});
Copier après la connexion
Copier après la connexion
Copier après la connexion

Supprimez start-server-and-test, en utilisant plutôt le serveur Web de Playwright

Pour tester mon application React, je devais d'abord la lancer (sur http://localhost:8080) dans un processus distinct, puis je pourrais exécuter mes tests. Ce serait le cas si j'utilisais Puppeteer ou Playwright. Avec Puppeteer, l'exemple Heroku utilisait le package start-server-and-test. Cependant, vous pouvez configurer Playwright pour lancer l'application avant d'exécuter des tests. C'est plutôt pratique !

J'ai supprimé start-server-and-test de mon projet.

~/project$ pnpm remove start-server-and-test
Copier après la connexion
Copier après la connexion

Dans playwright.config.js, j'ai décommenté la section webServer en bas, en la modifiant pour ressembler à ceci :

  /* Run your local dev server before starting the tests */
  webServer: {
     command: 'pnpm start',
     url: 'http://127.0.0.1:8080',
     reuseExistingServer: !process.env.CI,
  },
Copier après la connexion
Copier après la connexion

Ensuite, j'ai supprimé le script test:ci du fichier package.json d'origine. Au lieu de cela, mon script de test ressemblait à ceci :

  "scripts": {
    …
    "test": "playwright test --project=chromium --reporter list"
  },
Copier après la connexion
Copier après la connexion

Installer le navigateur Playwright sur mon ordinateur local

Playwright installe les derniers binaires du navigateur à utiliser pour ses tests. Donc, sur ma machine locale, j'avais besoin de Playwright pour installer sa version de Chromium.

~/project$ pnpm playwright install chromium


Downloading Chromium 130.0.6723.31 (playwright build v1140)
from https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip
164.5 MiB [====================] 100%
Copier après la connexion

Remarque : Le buildpack Chrome for Testing sur Heroku installe le navigateur que nous utiliserons pour les tests. Nous configurerons notre CI pour que Playwright utilise ce navigateur au lieu de consacrer du temps et des ressources à installer le sien.

Exécuter des tests localement

Avec ça, j’étais prêt. Il était temps de tester mes tests localement.

~/project$ pnpm test

> playwright test --project=chromium --reporter list

Running 3 tests using 3 workers

  ✓  1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (911ms)
  ✘  2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (5.2s)
  ✓  3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (959ms)

...
      - waiting for locator('a[href="https://playwright.dev/"]')


      13 | test.describe('Playwright link', () => {
      14 |   test('should navigate to Playwright documentation page', async ({ page }) => {
    > 15 |     await page.click('a[href="https://playwright.dev/"]');
         |                ^
      16 |     await expect(page.title()).resolves.toMatch('| Playwright');
      17 |   });
      18 | });
Copier après la connexion

Oh ! C'est exact. J'ai modifié mon test pour m'attendre à ce que le lien dans l'application me dirige vers la documentation de Playwright au lieu de celle de Puppeteer. J'avais besoin de mettre à jour src/App.js à la ligne 19 :

<Link href="https://playwright.dev/" rel="noopener">
  Playwright Documentation
</Link>
Copier après la connexion

Maintenant, il était temps de refaire les tests…

~/project$ pnpm test

> playwright test --project=chromium --reporter list

Running 3 tests using 3 workers

  ✓  1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (1.1s)
  ✓  2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (1.1s)
  ✓  3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (1.1s)

  3 passed (5.7s)
Copier après la connexion

Les tests ont réussi ! Ensuite, il était temps de nous amener sur Heroku CI.

Déployer sur Heroku pour utiliser CI Pipeline

J'ai suivi les instructions du billet de blog Heroku pour configurer mon application dans un pipeline Heroku CI.

Créer un pipeline Heroku

Dans Heroku, j'ai créé un nouveau pipeline et je l'ai connecté à mon dépôt GitHub forké.

Playwright and Chrome Browser Testing in Heroku

Ensuite, j'ai ajouté mon application à la mise en scène.

Playwright and Chrome Browser Testing in Heroku

Ensuite, je suis allé dans l'onglet Tests et j'ai cliqué sur Activer Heroku CI.

Playwright and Chrome Browser Testing in Heroku

Enfin, j'ai modifié le fichier app.json pour supprimer le script de test qui était configuré pour appeler npm test:ci. J'avais déjà supprimé le script test:ci de mon fichier package.json. Le script de test dans package.json était désormais celui à utiliser, et Heroku CI le rechercherait par défaut.

Mon fichier app.json, qui veillait à utiliser le buildpack Chrome for Testing, ressemblait à ceci :

~/project$ corepack enable pnpm


~/project$ corepack use pnpm@latest

Installing pnpm@9.12.3 in the project…
…
Progress: resolved 1444, reused 1441, downloaded 2, added 1444, done
…
Done in 14.4s

~/project$ rm package-lock.json


~/project$ pnpm install # just to show everything's good


Lockfile is up to date, resolution step is skipped
Already up to date
Done in 1.3s
Copier après la connexion
Copier après la connexion
Copier après la connexion

Test initial

J'ai poussé mon code vers GitHub, ce qui a déclenché un test dans Heroku CI.

Playwright and Chrome Browser Testing in Heroku

Le test a échoué, mais je n’étais pas inquiet. Je savais qu'il y aurait une configuration Playwright à faire.

En fouillant dans le journal de test, j'ai trouvé ceci :

~/project$ pnpm remove \
           babel-jest jest jest-puppeteer @testing-library/jest-dom

~/project$ $ pnpm create playwright
Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Do you want to use TypeScript or JavaScript? · JavaScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · false
✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · false
✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo pnpm exec playwright install-deps')? (y/N) · false

Installing Playwright Test (pnpm add --save-dev @playwright/test)…
…
Installing Types (pnpm add --save-dev @types/node)…
…
Done in 2.7s
Writing playwright.config.js.
Writing tests/example.spec.js.
Writing tests-examples/demo-todo-app.spec.js.
Writing package.json.
Copier après la connexion
Copier après la connexion
Copier après la connexion

Playwright recherchait l'instance du navigateur Chrome. Je pourrais l'installer avec la commande playwright install chromium dans le cadre de ma configuration de test CI. Mais cela irait à l’encontre de l’objectif même du buildpack Chrome for Testing. Chrome était déjà installé ; J'avais juste besoin de le souligner correctement.

En regardant en arrière dans mon journal de configuration de test pour Heroku, j'ai trouvé ces lignes :

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },

//    {
//      name: 'firefox',
//      use: { ...devices['Desktop Firefox'] },
//    },
//
//    {
//      name: 'webkit',
//      use: { ...devices['Desktop Safari'] },
//    },


  ],
…
Copier après la connexion
Copier après la connexion
Copier après la connexion

Donc, le navigateur que je voulais utiliser était /app/.chrome-for-testing/chrome-linux64/chrome. J'aurais juste besoin que Playwright le cherche là-bas.

Aider Playwright à trouver le navigateur Chrome installé

Remarque : Si vous n'êtes pas intéressé par les détails essentiels ici, vous pouvez ignorer cette section et simplement copier le app.json complet plus bas. Cela devrait vous donner ce dont vous avez besoin pour être opérationnel avec Playwright sur Heroku CI.

Dans la documentation de Playwright, j'ai découvert que vous pouvez définir une variable d'environnement qui indique à Playwright si vous avez utilisé un emplacement personnalisé pour toutes ses installations de navigateur. Cette variable d'environnement est PLAYWRIGHT_BROWSERS_PATH. J'ai décidé de commencer par là.

Dans app.json, j'ai défini une variable d'environnement comme celle-ci :

const ROOT_URL = 'http://localhost:8080';
const { test, expect } = require('@playwright/test');

const inputSelector = 'input[name="name"]';
const submitButtonSelector = 'button[type="submit"]';
const greetingSelector = 'h5#greeting';
const name = 'John Doe';

test.beforeEach(async ({ page }) => {
  await page.goto(ROOT_URL);
});

test.describe('Playwright link', () => {
  test('should navigate to Playwright documentation page', async ({ page }) => {
    await page.click('a[href="https://playwright.dev/"]');
    await expect(page.title()).resolves.toMatch('| Playwright');
  });
});

test.describe('Text input', () => {
  test('should display the entered text in the text input', async ({ page }) => {
    await page.fill(inputSelector, name);

    // Verify the input value
    const inputValue = await page.inputValue(inputSelector);
    expect(inputValue).toBe(name);
  });
});

test.describe('Form submission', () => {
  test('should display the "Hello, X" message after form submission', async ({ page }) => {
    const expectedGreeting = `Hello, ${name}.`;
    await page.fill(inputSelector, name);
    await page.click(submitButtonSelector);

    await page.waitForSelector(greetingSelector);
    const greetingText = await page.textContent(greetingSelector);
    expect(greetingText).toBe(expectedGreeting);
  });
});
Copier après la connexion
Copier après la connexion
Copier après la connexion

J'ai poussé mon code vers GitHub pour voir ce qui se passerait avec mes tests en CI.

Comme prévu, cela a encore échoué. Cependant, l'erreur de journal a montré ceci :

~/project$ corepack enable pnpm


~/project$ corepack use pnpm@latest

Installing pnpm@9.12.3 in the project…
…
Progress: resolved 1444, reused 1441, downloaded 2, added 1444, done
…
Done in 14.4s

~/project$ rm package-lock.json


~/project$ pnpm install # just to show everything's good


Lockfile is up to date, resolution step is skipped
Already up to date
Done in 1.3s
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela m'a rapproché. J'ai décidé de faire ceci :

  • Créez les dossiers nécessaires à l'endroit où Playwright s'attend à ce que le navigateur Chrome se trouve. Ce serait une commande du genre :
~/project$ pnpm remove \
           babel-jest jest jest-puppeteer @testing-library/jest-dom

~/project$ $ pnpm create playwright
Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Do you want to use TypeScript or JavaScript? · JavaScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · false
✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · false
✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo pnpm exec playwright install-deps')? (y/N) · false

Installing Playwright Test (pnpm add --save-dev @playwright/test)…
…
Installing Types (pnpm add --save-dev @types/node)…
…
Done in 2.7s
Writing playwright.config.js.
Writing tests/example.spec.js.
Writing tests-examples/demo-todo-app.spec.js.
Writing package.json.
Copier après la connexion
Copier après la connexion
Copier après la connexion
  • Créez un lien symbolique dans ce dossier pour pointer vers le binaire Chrome installé par le buildpack Heroku. Cela ressemblerait à ceci :
  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },

//    {
//      name: 'firefox',
//      use: { ...devices['Desktop Firefox'] },
//    },
//
//    {
//      name: 'webkit',
//      use: { ...devices['Desktop Safari'] },
//    },


  ],
…
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cependant, je me demandais si cela serait à l'épreuve du temps. À terme, Playwright utiliserait une nouvelle version de Chromium, et elle ne regarderait plus dans un dossier Chrome-1140. Comment pourrais-je savoir à quoi ressemblerait Playwright ?

C'est à ce moment-là que j'ai découvert que vous pouvez effectuer un essai d'installation du navigateur.

const ROOT_URL = 'http://localhost:8080';
const { test, expect } = require('@playwright/test');

const inputSelector = 'input[name="name"]';
const submitButtonSelector = 'button[type="submit"]';
const greetingSelector = 'h5#greeting';
const name = 'John Doe';

test.beforeEach(async ({ page }) => {
  await page.goto(ROOT_URL);
});

test.describe('Playwright link', () => {
  test('should navigate to Playwright documentation page', async ({ page }) => {
    await page.click('a[href="https://playwright.dev/"]');
    await expect(page.title()).resolves.toMatch('| Playwright');
  });
});

test.describe('Text input', () => {
  test('should display the entered text in the text input', async ({ page }) => {
    await page.fill(inputSelector, name);

    // Verify the input value
    const inputValue = await page.inputValue(inputSelector);
    expect(inputValue).toBe(name);
  });
});

test.describe('Form submission', () => {
  test('should display the "Hello, X" message after form submission', async ({ page }) => {
    const expectedGreeting = `Hello, ${name}.`;
    await page.fill(inputSelector, name);
    await page.click(submitButtonSelector);

    await page.waitForSelector(greetingSelector);
    const greetingText = await page.textContent(greetingSelector);
    expect(greetingText).toBe(expectedGreeting);
  });
});
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette ligne « Emplacement d’installation » était cruciale. Et, si nous définissons PLAYWRIGHT_BROWSERS_PATH, voici ce que nous verrions :

~/project$ pnpm remove start-server-and-test
Copier après la connexion
Copier après la connexion

C’est ce que je veux. Avec un peu de magie maladroite, j'ai fait ceci :

  /* Run your local dev server before starting the tests */
  webServer: {
     command: 'pnpm start',
     url: 'http://127.0.0.1:8080',
     reuseExistingServer: !process.env.CI,
  },
Copier après la connexion
Copier après la connexion

Avec tout cela compris, j'avais simplement besoin d'ajouter un script de configuration de test à app.json. Parce que PLAYWRIGHT_BROWSERS_PATH est déjà défini dans env, mon script serait un peu plus simple. C'était mon dernier fichier app.json :

  "scripts": {
    …
    "test": "playwright test --project=chromium --reporter list"
  },
Copier après la connexion
Copier après la connexion

Je vais brièvement expliquer ce que fait test-setup :

  1. Comptabilisation de PLAYWRIGHT_BROWSERS_PATH, utilise playwright install -- dry-run avec awk pour déterminer le dossier racine dans lequel Playwright recherchera le navigateur Chrome. Définit ceci comme valeur de la variable CHROMIUM_PATH.

  2. Crée un nouveau dossier (et tous les dossiers parents nécessaires) dans CHROMIUM_PATH/chrome-linux, qui est le dossier réel dans lequel Playwright recherchera le binaire Chrome.

  3. Crée un lien symbolique dans ce dossier, pour que Chrome pointe vers l'installation Heroku buildpack de Chrome (/app/.chrome-for-testing/chrome-linux64/chrome).

Réexécutez les tests

Avec mon fichier app.json mis à jour, Playwright devrait pouvoir utiliser l'installation de Chrome à partir du buildpack. Il était temps de refaire les tests.

Playwright and Chrome Browser Testing in Heroku

Succès !

Le script de configuration du test s'est exécuté comme prévu.

Playwright and Chrome Browser Testing in Heroku

Le dramaturge a pu accéder au binaire Chrome et exécuter les tests, qui ont réussi.

Playwright and Chrome Browser Testing in Heroku

Conclusion

Les tests de bout en bout de mes applications Web deviennent moins fastidieux, j'y donne donc de plus en plus la priorité. Ces derniers jours, cela signifie également utiliser davantage Playwright. C’est flexible et rapide. Et maintenant que j'ai fait le travail (pour moi et pour vous !) pour le rendre opérationnel avec le buildpack Chrome for Testing dans Heroku CI, je peux commencer à créer mes suites de tests d'automatisation de navigateur une fois encore une fois.

Le code de cette procédure pas à pas est disponible dans mon référentiel GitHub.

Bon codage !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal