Playwright测试自动化工具

作者观点:很长时间以来,Selenium是QA工程师寻求测试自动化解决方案的首选测试框架。它能够测试任何浏览器(这在IE浏览器的统治时期尤其重要)和任何平台。然而,现在看来,那个时代已经过去了。

今天,大多数web应用程序都是用现代前端框架开发的,如React、Angular或Next.js,所有的浏览器可以分为三类:基于Chromium引擎的浏览器,在Gecko上运行的Firefox,以及在WebKit上运行的Safari。

自Playwright出现以来,Chrome、Firefox和Safari都可以支持。这就消除了曾经普遍存在的需要跨浏览器框架的说法。所以,可以说Playwright涵盖了一切。

Playwright卓越的跨浏览器测试能力是由于其独特的架构。与Selenium不同,Playwright在API层面与浏览器进行交互,并绕过传统浏览器自动化框架的限制,从而能够更有效地发挥作用。这使得它更快,更可靠,更容易维护。

Playwright和Selenium一样,具有支持多种编程语言的独特优势,包括JavaScript、TypeScript、Java、Python和C#,这很容易集成到现有项目中,因此每个团队可以用他们最熟悉的语言工作。

总的来说,Playwright是一个强大而灵活的工具,可以帮助QA工程师简化测试过程,并使得web应用程序在所有主要的浏览器和平台上完美地运行。

为了总结Playwright官方网站上强调的突出功能,我们可以列出它们并逐一聊聊:

跨浏览器、跨平台和跨语言支持(Any browser • Any platform • One API)

弹性(Resilient • No flaky tests)

● 没有取舍的问题(No trade-offs • No limits)

● 简单的测试隔离和认证持久性(Full isolation • Fast execution)

● Visual Studio Code集成,测试代码生成以及选择器挑选(Powerful Tooling)

安装

有两种方法来安装该软件。

第一种方法是使用Node.js包管理器,如npm。如果选择这种方法,需要在电脑上安装Node.js。对于其他语言,Python使用pypi,Java使用Maven,C#可以使用 "dotnet add package "等.NET CLI命令来安装playwright的依赖项。

第二种方法是安装VSCode的playwright扩展,它带有方便的安装命令。这种方法能够让整个过程更顺畅、更容易。

Playwright的第一个特点(跨浏览器、跨平台和跨语言支持),我们可以说,它支持所有现代浏览器,在任何平台上都没有真正的限制。虽然它也支持流行的语言和技术,但支持的最好的语言是Typescript/Javascript。例如,如果你想在Java中使用Playwright,你需要选择你喜欢的测试运行器,如JUnit,并管理Playwright对象,如BrowserContext和Page。此外,你还需要为HTML报告找到一个解决方案。

● ● ●

当选择一个新的测试框架时,往往需要考虑权衡和限制。虽然现代测试框架通常专注于现代技术和前端框架,但QA工程师可能仍然需要处理用JSF等旧技术开发的遗留项目,以及使用iFrame或其后续的shadow-roots等组件的Web应用。因为,即便是Web应用组件的缓慢响应时间也会对现代测试框架构成真正的挑战。

根据我的经验,用Selenium自动化JSF应用程序要比用其他现代测试框架(如Playwright、Cypress或Puppeteer)更无缝。对于现代Web框架,我推荐Playwright或类似的测试框架。虽然任何Web应用程序仍然可以使用Selenium进行自动化,但具有许多影子根元素的应用程序可能需要一个更强大的方法。用Playwright穿透影子DOM可以使自动化变得更容易,而且脚本对未来的变化更有弹性。综上所述,选择Playwright并不需要很多取舍。然而,需要注意的是,它的重点是现代web应用和速度。

● ● ●

为了更好理解测试隔离的概念,我们首先应该看一下Playwright中的某些对象(objects)。要创建一个利用API库的自动化脚本,必须打开一个浏览器会话。现在,一个浏览器对象包含一些方法,其中之一是newContext()。正是这个对象能够开始一个新的会话,就像我们在电脑上开始一个新的隐身浏览器会话一样。而没有必要结束当前的主浏览器会话,例如,如果我们需要用不同的用户登录来检查变化。

python 复制代码
(async () => {
  const browser = await playwright.firefox.launch();  // Or 'chromium' or 'webkit'.
  
  // Create two isolated browser contexts
  const adminContext = await browser.newContext();
  const userContext = await browser.newContext();
  
  // Create pages and interact with contexts independently
  const adminPage = await adminContext.newPage();
  await adminPage.goto('https://example.com/admin');
 
  const userPage = await userContext.newPage();
  await userPage.goto('https://example.com/user');
 
  // Gracefully close up everything
  await adminContext.close();
  await userContext.close();
  await browser.close();
})();

Playwright还提供了一种方法来实现登录和在json文件中保存cookie会话。现有的会话可以在每次新的测试需要会话时使用,节省了登录应用程序的时间,大大减少了执行时间。

python 复制代码
// auth.setup.ts
import { test as setup } from '@playwright/test';
 
const authFile = 'playwright/.auth/user.json';
 
setup('authenticate', async ({ page }) => {
  // Perform authentication steps. Replace these actions with your own.
  await page.goto('https://github.com/login');
  await page.getByLabel('Username or email address').fill('username');
  await page.getByLabel('Password').fill('password');
  await page.getByRole('button', { name: 'Sign in' }).click();
  // End of authentication steps.
 
  await page.context().storageState({ path: authFile });
});

● ● ●

Playwright提供的工具很强大,然而必须注意的是,这只有在你使用VSCode时才有。如果选择Java和IntelliJ,就不能使用其中的一些功能。

Playwright的卖点之一无疑是其自动代码生成功能。虽然这个功能并不新鲜,其他框架也有这个功能,但首先生成代码,然后改进它,总是很实用

编写定位器和现场调试是相当有帮助的。可以节省时间,并通过观察元素定位器的解析位置来提高编写健壮脚本的能力。然而,我必须承认,当创建、调试和执行动作都在同一个窗口中进行时,实时调试可以得到改善,并使之更加流畅。

编写测试

我们已经看到了一些关于如何编写测试的代码。如果你选择用Library API编写测试,你将不得不管理像Browser、BrowserContext和Page这样的对象。

Playwright的好处是它为我们提供了一个playwright/test依赖项,它可以导出测试、页面和期望等固定装置。先看看一个简单的例子:

python 复制代码
import { test, expect } from '@playwright/test';
 
test('has title', async ({ page }) => {
  await page.goto('https://playwright.dev/');
 
  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);
});
 
test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');
 
  // Click the get started link.
  await page.getByRole('link', { name: 'Get started' }).click();
 
  // Expects the URL to contain intro.
  await expect(page).toHaveURL(/.*intro/);
});

在这个例子中,我们没有看到像Browser或BrowserContext这样的对象的创建。然而,我们必须知道,这些对象在我们的脚本中的每一次测试中都会自动创建和关闭。哪一个浏览器将被使用是在playwright.config文件中定义的。当然,不仅仅是使用哪个浏览器,还有很多配置可以在全局配置文件中定义。

运行测试

运行测试可以使用VSCode扩展或nodejs命令行。最简单的命令是npx playwright test。这个命令在TestDir(默认:./tests)中搜索所有扩展名为.spec.js或.spec.ts的文件。我们可以为特定的文件夹、文件、项目、无头选项等提供额外参数。更多细节,请参考官方文档(https://playwright.dev/docs/running-tests)。

固定装置(Fixtures)

如前所述,使用API库或Playwright Test编写测试是不同的。Playwright测试的基础是固定装置的概念,这基本上意味着我们正在创建一个环境,以便运行测试。Playwright带有一些内置的固定装置,其中一些是常用的。

● page类型的页面------测试运行的独立页面。

● BrowserContext类型的context------测试运行的孤立的上下文。页面夹具也属于这个上下文。

● browser of type 浏览器 ------浏览器在测试中被共享,以优化资源。

● browserName of type string------当前运行测试的浏览器的名称。可以是chromium、firefox或webkit。

● request of type APIRequestContext------测试运行的隔离的APIRequestContext实例。

如果我们遵循页面对象模型模式,我们可能会创建自己的页面类和对象实例。如果在多个测试中使用同一个实例,必须对测试进行分组,并在beforeEach hook中实例化该对象。我们可以使用 afterEach hook在每次测试执行结束时清理所有的东西。由于这可能是完美的工作,我们可以提取这段代码,并通过固定装置使其更可重复使用。让我们看看一个用页面对象制作的固定程序的例子:

python 复制代码
// my-test.js
const base = require('@playwright/test');
const { TodoPage } = require('./todo-page');
const { SettingsPage } = require('./settings-page');
 
// Extend base test by providing "todoPage" and "settingsPage".
// This new "test" can be used in multiple test files, and each of them will get the fixtures.
exports.test = base.test.extend({
  todoPage: async ({ page }, use) => {
    // Set up the fixture.
    const todoPage = new TodoPage(page);
    await todoPage.goto();
    await todoPage.addToDo('item1');
    await todoPage.addToDo('item2');
 
    // Use the fixture value in the test.
    await use(todoPage);
 
    // Clean up the fixture.
    await todoPage.removeAll();
  },
 
  settingsPage: async ({ page }, use) => {
    await use(new SettingsPage(page));
  },
});
exports.expect = base.expect;

这个夹具(fixture)现在扩展了内置的测试夹具(test fixtures)并实例化了TodoPage类对象。我们可以进行一些操作,并通过方法的使用(todoPage)暴露这个对象。这允许我们在测试中使用该对象,要做到这一点,必须从夹具中导入测试,如下所示:

python 复制代码
const { test, expect } = require('./my-test');

除了内置的固定装置,我们还可以使用自己的固定装置并将其结合起来。这些测试有干净的结构和一个抽象层,使测试更容易阅读。让我们看看完整的例子:

python 复制代码
const { test, expect } = require('./my-test');
 
test.beforeEach(async ({ settingsPage }) => {
  await settingsPage.switchToDarkMode();
});
 
test('basic test', async ({ todoPage, page }) => {
  await todoPage.addToDo('something nice');
  await expect(page.getByTestId('todo-title')).toContainText(['something nice']);
});

固定装置是Playwright的高级话题,但了解它们可以帮助我们解开Playwright的一些最佳功能。

总结

选择一个测试框架不是一件容易的事情,因为必须考虑到我们日常工作中的许多自动化场景。**我们最不想做的事情是:使用一个新的花哨的框架,然后在一段时间后因为它没有满足我们的需求而抛弃它。**可以看到,Playwright随着每个新版本的发布而逐渐成熟。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

相关推荐
七夜zippoe5 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
Fcy6486 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满6 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠7 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Harvey9037 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技8 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀8 小时前
Linux环境变量
linux·运维·服务器
zzzsde8 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器
零售ERP菜鸟8 小时前
范式革命:从“信息化”到“数字化”的本质跃迁
大数据·人工智能·职场和发展·创业创新·学习方法·业界资讯
聆风吟º10 小时前
CANN开源项目实战指南:使用oam-tools构建自动化故障诊断与运维可观测性体系
运维·开源·自动化·cann