JS `Playwright` / `Cypress` `Test Runner` 扩展与插件开发

各位观众老爷们,大家好!今天咱们来聊聊JS测试界两大“扛把子”——Playwright和Cypress的扩展与插件开发。别怕,这玩意儿听起来高大上,其实拆开揉碎了,也就那么回事儿。咱们争取用最接地气儿的方式,把这事儿给整明白。

开场白:测试界的“变形金刚”

Playwright和Cypress,就像测试界的“变形金刚”,本身能力就很强,但如果能给它们装上各种“外挂”,那简直是如虎添翼,战力爆表! 扩展和插件,就是这些“外挂”,它们能让你的测试流程更高效、更智能、更个性化。

第一部分:Playwright扩展开发

Playwright的扩展,其实是通过Browser Context来实现的。你可以理解为,Playwright允许你创建一个“定制浏览器环境”,在这个环境里,你可以注入一些自定义的脚本、修改请求、监听事件等等。

1.1 核心概念:Browser Context

Browser Context是Playwright的一个核心概念。每个Browser Context都有自己独立的存储空间(cookie、localStorage等等),就像不同的浏览器窗口一样。Playwright的扩展,主要就是围绕Browser Context展开的。

1.2 扩展的实现方式:browserType.launchPersistentContext()

想搞事情,首先得“启动一个持久化的浏览器上下文”。啥意思呢?就是创建一个Browser Context,并且把它保存在磁盘上。下次再启动的时候,可以直接加载这个上下文,而不需要重新创建。

const { chromium } = require('playwright');

async function createPersistentContext() {
  const browserType = chromium;
  const userDataDir = './my-user-data-dir'; // 指定用户数据目录

  const browserContext = await browserType.launchPersistentContext(userDataDir, {
    headless: false, // 别让浏览器偷偷摸摸地运行
    args: ['--disable-extensions-except=./my-extension', '--load-extension=./my-extension'], // 加载扩展
  });

  const page = await browserContext.newPage();
  await page.goto('https://www.example.com');

  // 这里可以做一些其他的操作,比如等待页面加载完成、点击按钮等等

  // browserContext.close(); // 别忘了关闭浏览器上下文
}

createPersistentContext();

代码解释:

  • chromium:指定使用Chromium浏览器。
  • userDataDir:指定用户数据目录,用于保存Browser Context的数据。
  • headless: false:设置浏览器以非headless模式运行,方便调试。
  • args:关键参数,用于加载扩展。
    • --disable-extensions-except=./my-extension:禁用所有扩展,除了./my-extension
    • --load-extension=./my-extension:加载./my-extension扩展。
  • page.goto('https://www.example.com'):打开网页。

1.3 创建你的第一个Playwright扩展

咱们来创建一个简单的扩展,让它在每个页面加载完成后,弹出一个提示框。

目录结构:

my-extension/
├── manifest.json
└── content.js

manifest.json: (扩展的配置文件)

{
  "manifest_version": 3,
  "name": "My Playwright Extension",
  "version": "1.0",
  "description": "A simple Playwright extension",
  "permissions": ["activeTab", "scripting"],
  "host_permissions": ["<all_urls>"],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_end"
    }
  ]
}

代码解释:

  • manifest_version: 必须是3
  • name:扩展的名称。
  • version:扩展的版本号。
  • description:扩展的描述。
  • permissions:扩展需要的权限。
    • activeTab:允许扩展访问当前活动标签页。
    • scripting: 允许扩展执行脚本
  • host_permissions: 允许扩展访问的域名
  • content_scripts:指定内容脚本。
    • matches:指定内容脚本生效的URL。
    • js:指定内容脚本的文件。
    • run_at:指定内容脚本的执行时机。document_end表示在文档加载完成后执行。

content.js: (扩展的核心逻辑)

alert('Hello from Playwright extension!');

代码解释:

  • alert('Hello from Playwright extension!'):在页面加载完成后,弹出一个提示框。

1.4 运行扩展

把上面的代码保存好,然后运行createPersistentContext()函数,你就能看到效果了。每次打开新的页面,都会弹出一个提示框。

1.5 扩展的进阶用法

除了弹出提示框,你还可以做更多的事情:

  • 修改请求: 使用browserContext.route()方法,可以拦截和修改请求。
  • 监听事件: 使用page.on()方法,可以监听各种事件,比如requestresponseconsole等等。
  • 注入脚本: 使用page.addScriptTag()方法,可以向页面注入自定义的脚本。
  • 操作DOM: 使用page.evaluate()方法,可以在页面中执行JavaScript代码,操作DOM。

第二部分:Cypress插件开发

Cypress的插件,是Cypress生态系统的重要组成部分。通过插件,你可以扩展Cypress的功能,比如集成第三方工具、修改Cypress的行为等等。

2.1 核心概念:cypress/plugins/index.js

cypress/plugins/index.js是Cypress插件的入口文件。Cypress在启动时,会自动加载这个文件。你可以在这个文件中注册各种插件,比如beforeaftertask等等。

2.2 插件的实现方式:module.exports = (on, config) => { ... }

cypress/plugins/index.js文件导出一个函数,这个函数接收两个参数:

  • on:用于注册事件监听器。
  • config:Cypress的配置对象。
// cypress/plugins/index.js
module.exports = (on, config) => {
  // 注册一个任务
  on('task', {
    'hello': (message) => {
      console.log('Hello from Cypress plugin! Message:', message);
      return 'Hello from plugin!'; // 返回值会被传递给测试用例
    },
  });

  // 注册一个before:browser:launch事件监听器
  on('before:browser:launch', (browser, launchOptions) => {
    console.log('Launching browser:', browser.name);

    // 可以修改launchOptions
    if (browser.name === 'chrome') {
      launchOptions.args.push('--disable-dev-shm-usage');
    }

    return launchOptions;
  });

  return config;
};

代码解释:

  • on('task', { ... }):注册一个任务。任务可以在测试用例中调用,用于执行一些自定义的操作。
    • 'hello': (message) => { ... }:定义一个名为hello的任务。
    • console.log('Hello from Cypress plugin! Message:', message):在控制台打印消息。
    • return 'Hello from plugin!':返回一个值,这个值会被传递给测试用例。
  • on('before:browser:launch', (browser, launchOptions) => { ... }):注册一个before:browser:launch事件监听器。这个事件在浏览器启动之前触发。
    • browser:浏览器对象。
    • launchOptions:浏览器的启动参数。
    • launchOptions.args.push('--disable-dev-shm-usage'):向Chrome浏览器添加启动参数。
  • return config:返回配置对象。

2.3 创建你的第一个Cypress插件

咱们来创建一个简单的插件,让它在测试用例中可以调用一个hello任务,打印一条消息。

目录结构:

cypress/
├── plugins/
│   └── index.js

cypress/plugins/index.js:

module.exports = (on, config) => {
  on('task', {
    'hello': (message) => {
      console.log('Hello from Cypress plugin! Message:', message);
      return 'Hello from plugin!';
    },
  });

  return config;
};

2.4 在测试用例中使用插件

// cypress/integration/example.spec.js
describe('My Cypress Test', () => {
  it('should call the hello task', () => {
    cy.task('hello', 'Hello from Cypress test!')
      .then((response) => {
        cy.log('Response from plugin:', response);
        expect(response).to.equal('Hello from plugin!');
      });
  });
});

代码解释:

  • cy.task('hello', 'Hello from Cypress test!'):调用名为hello的任务,并传递一个消息。
  • .then((response) => { ... }):处理任务的返回值。
  • cy.log('Response from plugin:', response):在控制台打印任务的返回值。
  • expect(response).to.equal('Hello from plugin!'):断言任务的返回值是否正确。

2.5 插件的进阶用法

Cypress插件的功能非常强大,你可以做很多事情:

  • 集成第三方工具: 比如集成代码覆盖率工具、性能测试工具等等。
  • 修改Cypress的行为: 比如修改Cypress的截图保存路径、修改Cypress的超时时间等等。
  • 自定义命令: 使用Cypress.Commands.add()方法,可以添加自定义的命令。
  • 操作数据库: 使用cy.task()方法,可以在插件中操作数据库。

第三部分:Playwright vs Cypress:扩展与插件的对比

| 特性 | Playwright for

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注