编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

jest-puppeteer:jest 与 puppeteer的一次强强联合!

wxchong 2024-10-02 01:33:47 开源技术 12 ℃ 0 评论

家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

今天给大家带来的主题是 jest-puppeteer,即一个使用 Jest 和 Puppeteer 运行测试的库。关于自动化测试以前也有发表过很多文章,下面是文章传送门:

话不多说,直接开始。

1.什么是 jest-puppeteer

Jest 是一个优秀的 Javascript 测试框架,可用于确保代码库的最终正确性,而且几乎是0配置,Jest 适用于使用 Babel、TypeScript、Node、React、Angular、Vue 等等的前端项目,还有众多大型企业的加持,比如:Facebook、Twitter、airbnb等等。在 Github上 Jest 有超过42k 的star、6.4k的fork、9283k的项目依赖量,代码贡献者1.5k,妥妥的前端明星开源项目。

而 Puppeteer 是一个 Node 库,它提供了诸多高级 API 以通过 DevTools 协议控制无头浏览器,如:Chrome、Firefox 和Chromium。 Puppeteer 可用于集成测试(单元测试关注的是隔离验证最小源代码块,集成测试用于发现不同块之间如何交互的错误), 它创建了一个可编程浏览器来检查站点,还可以模拟应用程序的实际用户体验。

那么什么是 jest-puppeteer 呢?jest-puppeteer 是一个 Jest 预设,可以使用 Puppeteer 进行端到端测试。 它提供了一个简单 API,用于启动新的浏览器实例并与网页交互。

目前 jest-puppeteer 在Github上通过 MIT 协议开源,有超过 3.5k 的star、300+ 的 fork,被 44.1k 的项目使用,代码贡献者70+,NPM 周平均下载量达到了 127k,是一个值得关注的前端自动化测试项目。

2.开始使用jest-puppeteer

安装依赖

第一步需要安装相应的依赖:

npm install --save-dev jest-puppeteer puppeteer jest

更新Jest配置

在 Jest 配置文件“jest.config.js”中添加 jest-puppeteer 作为预设:

{
  "preset": "jest-puppeteer"
}

写一个测试

要编写测试,请创建一个扩展名为 .test.js 的新文件,并使用 jest-puppeteer 公开的页面包含测试逻辑。 下面是使用的基本示例:

import "expect-puppeteer";

describe("Google", () => {
  beforeAll(async () => {
    await page.goto("https://google.com");
  });

  it('should display "google" text on page', async () => {
    await expect(page).toMatchTextContent("google");
  });
});

3.使用 Argos 进行视觉测试

配置Argos

Argos 是一个强大的可视化测试工具,允许审查每个pull请求引入的可视化更改。 通过将 Argos 与 jest-puppeteer 集成,开发者可以轻松捕获和比较屏幕截图,以确保应用程序的视觉一致性。

要开始使用 Argos,请按照以下步骤操作:

  • 安装 Argos GitHub 应用程序
  • 安装软件包
npm install --save-dev @argos-ci/cli @argos-ci/puppeteer
  • 在 E2E 测试期间截取屏幕截图:等待 argosScreenshot(page, "/screenshots/myScreenshot.png")
  • 在 CI 工作流中包含以下命令以将屏幕截图上传到 Argos:npx @argos-ci/cli upload ./screenshots

安装 Argos 后,了解如何查看开发工作流程中的视觉变化。

同步配置

// jest-puppeteer.config.cjs

/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */
module.exports = {
  launch: {
    dumpio: true,
    headless: process.env.HEADLESS !== "false" ? "new" : false,
  },
  server: {
    command: "node server.js",
    port: 4444,
    launchTimeout: 10000,
    debug: true,
  },
};

异步配置

在下面的示例中,通过将活动的 WebSocket 端点传递给连接选项来使用已运行的 Chrome 实例。 这在连接到在云中运行的 Chrome 实例时特别有用。

// jest-puppeteer.config.cjs
const dockerHost = "http://localhost:9222";

async function getConfig() {
  const data = await fetch(`${dockerHost}/json/version`).json();
  const browserWSEndpoint = data.webSocketDebuggerUrl;
  /** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */
  return {
    connect: {
      browserWSEndpoint,
    },
    server: {
      command: "node server.js",
      port: 3000,
      launchTimeout: 10000,
      debug: true,
    },
  };
}
module.exports = getConfig();

4.其他用法

使用 expect-puppeteer 库增强测试

使用 Puppeteer API 编写集成测试可能具有挑战性,因为它不是专门为测试目的而设计的。 为了简化编写测试过程,expect-puppeteer API 在 Puppeteer 页面上进行期望时提供了特定的匹配器。

下面的例子在页面中查找文本:

// Assert that the current page contains 'Text in the page'
await expect(page).toMatchTextContent("Text in the page");

下面的示例用于按钮点击:

// Assert that a button containing text "Home" will be clicked
await expect(page).toClick("button", { text: "Home" });

下面的示例用于填充表单数据:

// Assert that a form will be filled
await expect(page).toFillForm('form[name="myForm"]', {
  firstName: "James",
  lastName: "Bond",
});

调试模式

调试测试有时可能具有挑战性。 Jest Puppeteer 提供了一种调试模式,允许开发者暂停测试执行并检查浏览器。 要激活调试模式,请在测试中调用 jestPuppeteer.debug() :

await jestPuppeteer.debug();

请记住,使用 jestPuppeteer.debug() 将无限期地暂停测试。 要恢复,删除或注释掉该行并重新运行测试。 为了防止调试期间超时,请考虑增加 Jest 的默认超时:

jest.setTimeout(300000); 
// Set the timeout to 5 minutes (300000 ms)

服务器自动启动

Jest Puppeteer 允许在运行测试套件之前启动服务器,并在测试结束后关闭它。 要自动启动服务器,开发者必须将服务器部分添加到 jest-puppeteer.config.cjs 文件并指定启动服务器的命令和端口号:

// jest-puppeteer.config.cjs

/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */
module.exports = {
  server: {
    command: "node server.js",
    port: 4444,
  },
};

自定义 Puppeteer 实例

要自定义 Puppeteer 实例,开发者可以更新 jest-puppeteer.config.cjs 文件。

例如,要启动 Firefox 浏览器而不是默认的 chrome,可以将 launch.product 属性设置为“firefox”。还可以更新浏览器上下文以使用隐身模式在实例之间进行隔离。

默认配置值如下:

// jest-puppeteer.config.cjs

/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */
module.exports = {
  launch: {
    dumpio: true,
    headless: process.env.HEADLESS !== "false" ? "new" : false,
    product: "chrome",
  },
  browserContext: "default",
};

自定义 setupTestFrameworkScriptFile 或 setupFilesAfterEnv

如果使用的是自定义设置文件,则必须在设置中包含 expect-puppeteer 才能访问它提供的匹配器。 可以将以下内容添加到自定义安装文件中:

// setup.js
require("expect-puppeteer");

// Your custom setup
// ...
// jest.config.js
module.exports = {
  // ...
  setupTestFrameworkScriptFile: "./setup.js",
  // or
  setupFilesAfterEnv: ["./setup.js"],
};

设置自定义 setupFilesAfterEnv 和 globalSetup 时要小心,因为它可能会导致未定义的全局变量。 在 Jest 中使用多个项目是缓解此问题的一种方法。


module.exports = {
  projects: [
    {
      displayName: "integration",
      preset: "jest-puppeteer",
      transform: {
        "\\.tsx?#34;: "babel-jest",
        ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)#34;:
          "jest-transform-stub",
      },
      moduleNameMapper: {
        "^.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)#34;:
          "jest-transform-stub",
      },
      modulePathIgnorePatterns: [".next"],
      testMatch: [
        "<rootDir>/src/**/__integration__/**/*.test.ts",
        "<rootDir>/src/**/__integration__/**/*.test.tsx",
      ],
    },
    {
      displayName: "unit",
      transform: {
        "\\.tsx?#34;: "babel-jest",
        ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)#34;:
          "jest-transform-stub",
      },
      moduleNameMapper: {
        "^.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)#34;:
          "jest-transform-stub",
      },
      globalSetup: "<rootDir>/setupEnv.ts",
      setupFilesAfterEnv: ["<rootDir>/setupTests.ts"],
      modulePathIgnorePatterns: [".next"],
      testMatch: [
        "<rootDir>/src/**/__tests_/**/*.test.ts",
        "<rootDir>/src/**/__tests__/**/*.test.tsx",
      ],
    },
  ],
};

扩展 Puppeteer 环境

如果需要使用自定义环境,可以扩展 Puppeteer 环境。

首先,为自定义环境创建一个 JavaScript 文件:

// custom-environment.js
const PuppeteerEnvironment = require("jest-environment-puppeteer");

class CustomEnvironment extends PuppeteerEnvironment {
  async setup() {
    await super.setup();
    // Your setup
  }

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

module.exports = CustomEnvironment;

接下来,将 JavaScript 文件的路径分配给 Jest 配置中的 testEnvironment 属性:

{
  // ...
  "testEnvironment": "./custom-environment.js"
}

自定义setup和teardown现在将分别在每个测试套件之前和之后执行。

实现自定义 globalSetup 和 globalTeardown

开发者可以创建自定义 globalSetup 和 globalTeardown 方法。 为此,jest-environment-puppeteer 公开了setup和teardown方法,允许将它们与自定义全局设置和拆卸方法集成,如下例所示:

// global-setup.js
const setupPuppeteer = require("jest-environment-puppeteer/setup");

module.exports = async function globalSetup(globalConfig) {
  await setupPuppeteer(globalConfig);
  // Your global setup
};
// global-teardown.js
const teardownPuppeteer = require("jest-environment-puppeteer/teardown");

module.exports = async function globalTeardown(globalConfig) {
  // Your global teardown
  await teardownPuppeteer(globalConfig);
};

然后将 js 文件路径分配给 Jest 配置中的 globalSetup 和 globalTeardown 属性。

{
  // ...
  "globalSetup": "./global-setup.js",
  "globalTeardown": "./global-teardown.js"
}

现在,自定义 globalSetup 和 globalTeardown 将分别在所有测试套件之前和之后执行一次。

配置 Jest-Puppeteer

Jest Puppeteer 使用 cosmiconfig 来支持配置文件,允许以各种方式配置 Jest Puppeteer(按优先顺序列出):

  • package.json 文件中的 jest-puppeteer 键
  • JSON 或 YAML 格式的 .jest-puppeteerrc 文件
  • .jest-puppeteerrc.json、.jest-puppeteerrc.yml、.jest-puppeteerrc.yaml 或 .jest-puppeteerrc.json5 文件
  • 使用 module.exports 导出对象的 .jest-puppeteerrc.js、.jest-puppeteerrc.cjs、jest-puppeteer.config.js 或 jest-puppeteer.config.cjs 文件
  • 一个 .jest-puppeteerrc.toml 文件

默认情况下,在项目的根目录中搜索配置,如果要定义自定义路径,请使用 JEST_PUPPETEER_CONFIG 环境变量。但是,需要确保导出的配置是配置对象或返回配置对象的 Promise。

interface JestPuppeteerConfig {
  /**
   * Puppeteer connect options.
   * @see https://pptr.dev/api/puppeteer.connectoptions
   */
  connect?: ConnectOptions;
  /**
   * Puppeteer launch options.
   * @see https://pptr.dev/api/puppeteer.launchoptions
   */
  launch?: PuppeteerLaunchOptions;
  /**
   * Server config for `jest-dev-server`.
   * @see https://www.npmjs.com/package/jest-dev-server
   */
  server?: JestDevServerConfig | JestDevServerConfig[];
  /**
   * Allow to run one browser per worker.
   * @default false
   */
  browserPerWorker?: boolean;
  /**
   * Browser context to use.
   * @default "default"
   */
  browserContext?: "default" | "incognito";
  /**
   * Exit on page error.
   * @default true
   */
  exitOnPageError?: boolean;
  /**
   * Use `runBeforeUnload` in `page.close`.
   * @see https://pptr.dev/api/puppeteer.page.close
   * @default false
   */
  runBeforeUnloadOnClose?: boolean;
}

5.本文总结

本文主要和大家介绍下 jest-puppeteer,即一个使用 Jest 和 Puppeteer 运行测试的库。相信通过本文的阅读,大家对 jest-puppeteer 会有一个初步的了解。

因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!

参考资料

https://github.com/argos-ci/jest-puppeteer/

https://github.com/jestjs/jest

https://jestjs.io/

https://www.sanity.io/guides/testing-with-jest-and-puppeteer

https://www.npmjs.com/package/jest-puppeteer

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表