当前位置:首页 > 编程语言 > 正文内容

使用Puppeteer轻松进行端到端React应用测试

a811625532年前 (2023-12-28)编程语言16

测试是软件开发中的必修课,有许多可行的工具来完成这项任务。本文将探讨 Puppeteer 如何使自动化测试变得简单而有效,并将教您如何为 React 应用程序编写简单、高效的 E2E 测试,以及如何使用 Puppeteer 从用户角度进行测试。

软件测试是软件开发生命周期(SDLC)的一个重要方面。对应用程序进行测试势在必行,因为这样做可以帮助您及早发现编写代码中的错误和缺陷,并使您能够构建符合预期的高质量标准软件。

然而,许多组织仍然严重依赖效率低下的手动测试 *** 。统计数据为实施更多的自动化测试提供了令人信服的理由。研究表明,的,但只有 5% 的公司进行了完全自动化的测试。三分之二的公司以 的比例进行测试。

预计 2021-2026 年间,,因此测试自动化是跟上市场步伐的关键。一项研究发现,79% 的最终用户在 2019 年仍会遇到错误,这表明需要更好的测试。70% 的 IT 领导者肯定自动化测试能带来更高的效率,因此自动化趋势只增不减。 等解决方案可实现简化的端到端(E2E)测试,帮助组织和公司提高软件质量和用户体验。

什么是 Puppeteer?

谷歌开发的一个 Node.js 库,用于自动化前端测试过程。它提供高级 API,可通过 协议控制 Chrome 浏览器或基于 Chromium 的浏览器。它允许测试人员执行无头和有头操作。

无头与有头浏览器操作

无头浏览器是一种没有图形用户界面(GUI)的浏览器。它们通过命令行界面或 *** 通信执行。-

Puppeteer 允许以无头模式(不显示浏览器用户界面)或有头模式(显示浏览器用户界面)控制 Chrome 或 Chromium。虽然无头模式是默认模式,但有头模式也有助于调试。与无头模式浏览器相比,网站也更难检测到由脚本控制的有头模式浏览器。

Puppeteer 的应用领域:

  • 自动化大多数用户界面测试,包括键盘和鼠标移动
  • 执行端到端测试
  • 网页抓取和刮擦
  • 生成屏幕截图和 PDF
  • 捕捉网站的时间线轨迹,帮助诊断性能问题
  • 自动提交表单

什么是 Jest

是一个开源 ,旨在测试 React 和 React Native *** 应用程序。

通常,软件前端的 E2E 测试过于繁琐,因为需要进行大量耗时的配置。然而,使用 Jest 进行测试可以更大限度地减少单元测试所需的配置,从而降低前端测试的复杂性。

设置项目

在本节中,你将使用 Puppeteer 和 Jest 配置一个。首先,你将使用引导一个新的 React 应用程序。

运行以下命令:

npx create-react-app react-puppeteer-test

接下来,创建项目目录和 react-puppeteer-test 应用程序后,导航到新创建的目录,并在终端运行以下命令安装以下软件包:

  • Jest – 我们的测试运行程序
  • Puppeteer – 我们的浏览器自动化工
  • – 运行 Puppeteer 测试的 Jest 插件
npm install puppeteer jest jest-puppeteer

设置好应用程序后,在终端中输入以下任一命令运行应用程序:

yarn start

或使用 :

npm start

服务器应在浏览器 http://localhost:3000/ 中启动,如下图所示:

配置 Jest 设置

Jest 默认情况下运行良好,但有时您需要更多配置功能。首先,在项目根目录下创建一个名为 jest.config.js 的文件,设置 Jest 配置。用以下代码段填充该文件:

module.exports = {
preset: "jest-puppeteer",
testMatch: ["**/src/__tests__/**/*.test.js"],
verbose: true,
};

此配置指示 Jest 使用 jest-puppeteer 预设,并将测试放在 __tests__ 文件夹中。

package.json 文件中添加相应的脚本:

"scripts": {
"test": "jest"
}

该命令指示 Jest 处理测试脚本。您已在应用程序中成功配置了 Jest。

配置 Puppeteer 设置

接下来,在项目根文件夹中创建一个名为 jest-puppeteer.config.js 的文件,并粘贴以下代码段以创建 Puppeteer 配置:

module.exports = {
launch: {
headless: process.env.HEADLESS !== "false",
slowMo: process.env.SLOWMO ? parseInt(process.env.SLOWMO, 10) : 0,
devtools: process.env.DEVTOOLS === "true",
product: "chrome",
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
"--disable-accelerated-2d-canvas",
"--disable-gpu",
"--window-size=1920,1080",
],
},
};

该配置规定在无头模式下运行 Puppeteer,避免使用沙箱,禁用 GPU 并设置窗口大小。它还允许自定义浏览器产品(Chrome 或 Firefox),并引入了减缓测试执行速度以提高可视性的选项。

使用 Puppeteer 的测试示例

关于使用 Puppeteer 和 Jest 进行的基本测试,请参考以下使用示例。

在本教程中,我将指导你使用 Puppeteer 进行之一次自动测试。如果你阅读了本节内容,说明你已经在项目中安装并设置了 Puppeteer。如果还没有,请按照上面的说明操作。如果你已经安装,那就让我们开始吧。

创建测试文件。你必须创建实际的测试文件来进行测试。为此,您必须在某些目录中合理安排测试文件的结构。在终端运行以下命令:

cd src && mkdir __tests__ && cd __tests__ && touch homepage.test.js

上述命令的作用是

  • 将目录更改为 src 文件夹;
  • 将目录更改为 __tests__ 文件夹;
  • 创建一个名为 homepage.test.js 的新文件
// src/__tests__/homepage.test.js
const puppeteer = require("puppeteer");
describe("OpenReplay.com page", () => {
let browser;
let page;
beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
});
it("should contain text", async () => {
await page.goto("https://openreplay.com/", { waitUntil: 'networkidle2' });
await page.waitForSelector(".display-4");
const text = await page.$eval(".display-4", (e) => e.textContent);
expect(text).toContain(`Session replay`);
});
afterAll(() => browser.close());
});

上面这段代码的作用是

  • 首先描述您的 E2E 测试
  • 浏览测试网站
  • 您正在测试 display-4 类是否包含网站上的 Session replay 文本。beforeAll 函数启动 Puppeteer 实例,创建浏览器和页面。测试使用页面的选择器检查是否存在指定文本。

这可以作为创建自定义测试的模板。现在,让我们来探讨一个实际场景。

真实世界示例:测试登录表单

考虑一个登录表单组件:

// App.js
import { useState } from "react";
import "./App.css";
function App() {
const [isUserLoggedIn, setIsUserLoggedIn] = useState(false);
const [error, setError] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const login = (event) => {
event.preventDefault();
if (email === "admin@openreplay.com" && password === "password") {
setIsUserLoggedIn(true);
} else {
setIsUserLoggedIn(false);
setError(true);
setTimeout(() => {
setError(false);
}, 4000);
}
};
return (
<div className="App">
<div className="form-wrapper">
<h1 className="form-header">Welcome back</h1>
{!isUserLoggedIn && (
<form className="form" onSubmit={login}>
{error && (
<p className="form-error-text">
Invalid email or password
</p>
)}
<input
type="email"
required
placeholder="Email Address"
className="form-input form-input__email"
onChange={(e) => {
setEmail(e.target.value);
}}
name="emailAddress"
/>
<input
type="password"
required
placeholder="Password"
className="form-input form-input__password"
onChange={(e) => {
setPassword(e.target.value);
}}
name="password"
/>
<button type="submit" className="form-submit-button">
Submit
</button>
</form>
)}
{isUserLoggedIn && (
<p className="form-success-message">Login successful.</p>
)}
</div>
</div>
);
}
export default App;

在上面的代码中,我们模拟了一个登录场景:

  1. 我们使用 useState 钩子初始化了状态变量 isUserLoggedInerroremailpassword
  2. login 函数处理表单提交、检查凭证并相应更新状态。
  3. *** X 会根据用户的登录状态渲染一个包含电子邮件、密码输入和提交按钮的表单。
  4. 如果登录尝试失败,会显示一条错误信息,并在 4 秒后消失。
  5. 只有当用户名是 admin@openreplay.com 且密码是 password 时,登录才会成功。
  6. 用户登录后会显示一条成功信息。
  7. 该组件将作为默认导出组件导出,供应用程序其他部分使用。

// App.test.js
import puppeteer from "puppeteer";
describe("App.js", () => {
let browser;
let page;
beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
});
it("shows a success message after submitting a form", async () => {
await page.goto("http://localhost:5000");
await page.waitForSelector(".form-header");
await page.click(".form-input__email");
await page.type(".form-input__email", "admin@openreplay.com");
await page.click(".form-input__password");
await page.type(".form-input__password", "password");
await page.click(".form-submit-button");
await page.waitForSelector(".form-success-message");
const text = await page.$eval(
".form-success-message",
(e) => e.textContent
);
expect(text).toContain("Login successful.");
});
it("shows an error message if authentication fails", async () => {
await page.goto("http://localhost:5000");
await page.waitForSelector(".form-header");
await page.click(".form-input__email");
await page.type(".form-input__email", "admin@openreplay.com");
await page.click(".form-input__password");
await page.type(".form-input__password", "password123");
await page.click(".form-submit-button");
await page.waitForSelector(".form-error-text");
const text = await page.$eval(".form-error-text", (e) => e.textContent);
expect(text).toContain("Invalid email or password");
});
afterAll(() => browser.close());
});

上述测试示例 ⬆ 演示了使用 Puppeteer 和 Jest 测试登录表单。它包括导航到应用程序、与表单元素交互以及验证预期结果。

  1. 它包括 beforeAll 块中的设置代码、启动 Puppeteer 浏览器实例以及在任何测试前创建新页面。
  2. 之一个测试( it )检查使用有效凭证提交表单后是否显示成功消息(Login successful.)。
  3. 在之一个测试中,表单的交互方式是导航到指定的 URL,填写电子邮件和密码字段,单击提交按钮,然后验证是否出现成功消息。
  4. 第二个测试将检查在尝试使用无效凭据进行身份验证时是否显示错误消息。
  5. 与之一个测试类似,第二个测试通过导航到 URL、输入无效电子邮件和密码、单击提交按钮以及验证是否出现错误消息(Invalid email or password)来与表单交互。AfterAll 块确保在完成所有测试后关闭 Puppeteer 浏览器实例。

探索 Puppeteer 的调试功能

Puppeteer 提供了多种调试选项,可用于 React 应用程序的端到端测试。让我们来探索这些选项,并演示如何将它们整合到现有测试中。

在无头模式下运行

Puppeteer 默认以无头模式启动 Chromium 浏览器,这意味着没有可见的用户界面。这非常适合自动化测试和服务器环境。不过,如果你想在测试执行期间观察浏览器,可以通过设置 headless: false 来启动完整版浏览器:

beforeAll(async () => {
browser = await puppeteer.launch({ headless: false });
page = await browser.newPage();
});

运行测试时,将显示一个 Chromium 浏览器窗口。

减慢测试执行速度

在无头模式下,某些操作(如表单提交)可能发生得太快,无法观察。为了解决这个问题,Puppeteer 提供了 slowMo 选项,可以延迟 Puppeteer 的执行。

例如,可按如下 *** 将速度减慢 300 毫秒:

beforeAll(async () => {
browser = await puppeteer.launch({
headless: false,
slowMo: 300, // slow down by 300ms
});
page = await browser.newPage();
});

这样就能更好地跟踪测试执行情况。

使用 page.emulate 模拟设备

使用 page.emulate() *** 可以模拟设备指标和用户 *** 。您可以自定义视口尺寸和用户 *** 等属性:

beforeAll(async () => {
browser = await puppeteer.launch({ headless: false });
page = await browser.newPage();
page.emulate({
viewport: {
width: 500,
height: 900,
},
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
deviceScaleFactor: 1,
isMobile: false,
hasTouch: false,
isLandscape: false,
});
});

Puppeteer 为简化仿真提供了设备描述符列表,可通过 puppeteer.devices 访问。例如,模拟 iphone 7:

const iPhone = puppeteer.devices['iPhone 7'];
beforeAll(async () => {
browser = await puppeteer.launch({
headless: false,
slowMo: 300, // slow down by 300ms
});
page = await browser.newPage();
await page.emulate(iPhone);
});

使用 Jest Puppeteer

Jest Puppeteer 简化了运行 Puppeteer 测试的配置。请按照以下步骤进行设置:

使用 yarn add -D jest-puppeteer 安装 Jest Puppeteer。创建 jest.config.js 文件:

module.exports = {
preset: "jest-puppeteer",
testRegex: "./*\\e2e\\.test\\.js$",
};

创建 jest-puppeteer.config.js 文件:

module.exports = {
server: {
command: "yarn start",
port: 3000,
launchTimeout: 10000,
debug: true,
},
};

Jest Puppeteer 无需在测试前构建生产网站,从而简化了测试流程。

运行中的 Jest Puppeteer

修改测试文件(如 e2e.test.js )以利用 Jest Puppeteer 的功能:

// ... (existing setup)
describe("App.js", () => {
it("shows a success message after submitting a form", async () => {
// ... (existing test logic)
});
it("shows an error message if authentication fails", async () => {
// ... (existing test logic)
});
});

Jest Puppeteer 更大限度地减少了设置,并为表单填写、按钮点击和文本匹配提供了更简洁的语法。

运行测试前,更新 App.js 中的表单,为电子邮件和密码输入添加名称属性。

<input
type="email"
required
placeholder="Email Address"
className="form-input form-input__email"
onChange={(e) => {
setEmail(e.target.value);
}}
name="emailAddress"
/>
<input
type="password"
required
placeholder="Password"
className="form-input form-input__password"
onChange={(e) => {
setPassword(e.target.value);
}}
name="password"

更新 .eslintrc.js 文件,确保 ESLint 兼容性:

module.exports = {
env: {
jest: true,
},
globals: {
page: true,
browser: true,
context: true,
jestPuppeteer: true,
},
};

使用 yarn test:e2e 执行测试,获得所有测试通过的简明输出。

通过使用这些 Puppeteer 调试选项和 Jest Puppeteer,你可以简化测试流程,确保 React 应用程序的端到端测试功能强大。

小结

本文深入介绍了如何使用 Puppeteer 和 Jest 进行端到端测试。实际示例展示了登录表单的测试,强调了导航、元素识别和用户操作模拟。将这些原则纳入您的测试工作流程,以实现强大的 React 应用测试。

在 上查看本文的资源库

扫描二维码推送至手机访问。

版权声明:本文由2345好导航站长资讯发布,如需转载请注明出处。

本文链接:http://2345hao.cn/blog/index.php/post/8150.html

分享给朋友:

“使用Puppeteer轻松进行端到端React应用测试” 的相关文章

宝塔面板教程之数据库管理篇

宝塔面板教程之数据库管理篇

宝塔的数据库管理,是基于phpmyadmin管理和新建数据库。其最大的便利性就是类似,通过面板可以快速访问进行管理操作,无需单独访问phpmyadmin的主页。 此外,在宝塔面板进行数据库管理,你也对数据库名、用户名及密码等信息一目了然,及可以对数据库执行快速备份或者导入。 添加数据...

宝塔面板教程之监控管理篇

宝塔面板教程之监控管理篇

宝塔面板另外一个特质是,你无需通过Linux命令行来查看服务器各项指标状况,即可以阿里云服务器类似的可视化图表,查看资源使用、负载、CPU占用及内容使用百分比等指标。 默认监控是关闭,有需要的,可以开启,监控数据默认保存30天,可以自行修改,默认监控数据保存在日志,可手动清理该日志。 监控管理,...

20个最佳Laravel免费和付费教程资源

20个最佳Laravel免费和付费教程资源

Laravel多年来一直是PHP应用程序开发的摇滚明星,这是有充分理由的。庞大的生态系统、活跃的社区、强大的就业市场、成功的初创公司——它拥有一切让采用新技术变得值得的东西。 如果你想学习Laravel,你不需要更进一步。通过浏览本指南,您可以找到最适合您的Laravel教程,与您的知识水平和...

如何成为一名出色的Java开发人员

如何成为一名出色的Java开发人员

美国劳工统计局估计在美有超过软件开发人员。根据2021年的数据,其中,这是世界上使用最广泛的五种编程语言之一。 自然,学习Java并成为Java开发人员对于任何对软件开发感兴趣的人来说都是明智的职业选择。 在本综合指南中,您将学习成为Java开发人员所需的一切知识。我们将分解您需要的技能、工...

Serverless PHP简介:主要功能、用例以及如何在Lambda上开始使用Bref

Serverless PHP简介:主要功能、用例以及如何在Lambda上开始使用Bref

无服务器计算是一种基于云的执行模型,可以将应用程序作为服务托管,而无需维护服务器。 服务提供商维护服务器上的资源分配,并根据实际使用情况向用户收费。焦点转移到一个人正在创建的核心应用程序上,基础设施完全由服务提供商处理。无服务器计算也称为功能即服务 (FaaS)。 换句话说,Serverle...

Cloudflare即将完全弃用Host API集成

Cloudflare即将完全弃用Host API集成

Cloudflare已宣布弃用HOST API集成,这将影响Cloudflare的传统主机和经销商合作伙伴。 Cloudflare弃用HOST API Cloudflare Legacy Host API将于2022年11月1日正式被弃用。Cloudflare表示,由于支持和维护程序...