簡體   English   中英

Puppeteer 使用單個瀏覽器實例運行所有測試文件

[英]Puppeteer Run All Test Files With Single Browser Instance

我有 30 種不同的測試,這些測試基於puppeteer並使用jest 每個都有不同的流程,我想通過只運行每個測試一個瀏覽器並創建新選項卡而不是為每個測試文件創建新的瀏覽器實例來減少系統和網絡負載。

這樣做的問題很少:

  • 如何在測試文件之間共享一個瀏覽器實例? 因為它是異步過程並且在 Node.js 中沒有異步導出

    const browser = await puppeteer.launch({ headless: false });

  • 如何理解所有測試套件都已完成,是時候關閉瀏覽器了? 我可以在測試完成后關閉頁面,但我不知道哪個測試將是最后一個測試,或者如果它失敗了怎么辦?

PS(致編輯):這不是重復的線程,為 C# 打開了類似的線程,環境完全不同。 Puppeteer - 在多個測試中運行 1 個瀏覽器實例

Jest's Docs 中有一個關於如何重用瀏覽器實例的非常簡潔的指南

您最終將擁有以下結構:

[root]
...
+-- jest.config.js
+-- puppeteer_environment.js
+-- setup.js
+-- teardown.js
+-- test.js
  • jest.config.js [jest]:這是 Jest 的默認配置文件,您將在此處連接其他設置文件,以便 Jest 使用自定義 puppeteer
  • setup.js [puppeteer]:只啟動一次 puppeteer
  • puppeteer_environment.js puppeteer_environment.js puppeteer]:自定義環境 Class 連接到正確的 websocket
  • teardown.js [puppeteer]:最后關閉瀏覽器實例
  • test.js [test]:這是一個示例 Jest 測試文件,重要的部分是在beforeAll全局中定義 page 為:
page = await globalThis.__BROWSER_GLOBAL__.newPage();

免責聲明:以下示例是從鏈接頁面復制的,它被許多測試項目用作樣板,其中創建者不願意使用jest-puppeteer預設,而是使用puppeteer設置自定義jest環境。


“[...] 基本思想是:

  1. 使用全局設置啟動並歸檔 puppeteer 的 websocket 端點
  2. 從每個測試環境連接到 puppeteer
  3. 使用 Global Teardown 關閉 puppeteer

這是 GlobalSetup 腳本的示例?

setup.js

const {mkdir, writeFile} = require('fs').promises;
const os = require('os');
const path = require('path');
const puppeteer = require('puppeteer');

const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');

module.exports = async function () {
  const browser = await puppeteer.launch();
  // store the browser instance so we can teardown it later
  // this global is only available in the teardown but not in TestEnvironments
  globalThis.__BROWSER_GLOBAL__ = browser;

  // use the file system to expose the wsEndpoint for TestEnvironments
  await mkdir(DIR, {recursive: true});
  await writeFile(path.join(DIR, 'wsEndpoint'), browser.wsEndpoint());
};

然后我們需要一個自定義的 puppeteer 測試環境

puppeteer_environment.js

const {readFile} = require('fs').promises;
const os = require('os');
const path = require('path');
const puppeteer = require('puppeteer');
const NodeEnvironment = require('jest-environment-node').default;

const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');

class PuppeteerEnvironment extends NodeEnvironment {
  constructor(config) {
    super(config);
  }

  async setup() {
    await super.setup();
    // get the wsEndpoint
    const wsEndpoint = await readFile(path.join(DIR, 'wsEndpoint'), 'utf8');
    if (!wsEndpoint) {
      throw new Error('wsEndpoint not found');
    }

    // connect to puppeteer
    this.global.__BROWSER_GLOBAL__ = await puppeteer.connect({
      browserWSEndpoint: wsEndpoint,
    });
  }

  async teardown() {
    await super.teardown();
  }

  getVmContext() {
    return super.getVmContext();
  }
}

module.exports = PuppeteerEnvironment;

最后,我們可以關閉 puppeteer 實例並清理文件

拆解.js

const fs = require('fs').promises;
const os = require('os');
const path = require('path');

const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
module.exports = async function () {
  // close the browser instance
  await globalThis.__BROWSER_GLOBAL__.close();

  // clean-up the wsEndpoint file
  await fs.rm(DIR, {recursive: true, force: true});
};

設置好所有東西后,我們現在可以像這樣編寫測試:

測試.js

const timeout = 5000;

describe(
  '/ (Home Page)',
  () => {
    let page;
    beforeAll(async () => {
      page = await globalThis.__BROWSER_GLOBAL__.newPage();
      await page.goto('https://google.com');
    }, timeout);

    it('should load without error', async () => {
      const text = await page.evaluate(() => document.body.textContent);
      expect(text).toContain('google');
    });
  },
  timeout,
);

最后,設置jest.config.js從這些文件中讀取。 jest-puppeteer預設在引擎蓋下做了類似的事情。)

module.exports = {
  globalSetup: './setup.js',
  globalTeardown: './teardown.js',
  testEnvironment: './puppeteer_environment.js',
};

"

鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM