深入分析 Cypress/Playwright 等端到端测试工具如何与 Vue 应用进行集成,并进行自动化测试。

各位观众老爷们,大家好!今天咱就来聊聊Vue应用和端到端测试工具(Cypress和Playwright)那点事儿。保证让大家听完,感觉就像打通了任督二脉,测试代码刷刷刷地写!

咱们先来热热身,说说端到端测试是啥玩意儿?

想象一下,你开发了一个精美的Vue应用,用户打开网页,点击按钮,输入信息,提交表单,页面跳转…这一系列操作构成了一个完整的使用流程。端到端测试,就是模拟用户真实的操作,验证整个流程是不是顺畅,有没有Bug。

简单来说,就是把你的应用当成一个黑盒子,输入一些东西,看看输出是不是符合预期。

为啥要用端到端测试?

  • 更接近用户体验: 能发现集成测试和单元测试无法发现的问题,例如路由跳转错误,数据渲染问题等等。
  • 覆盖面广: 可以覆盖应用的多个组件和模块,确保它们协同工作正常。
  • 减少回归Bug: 每次代码更新后运行测试,可以快速发现引入的新Bug。

主角登场:Cypress 和 Playwright

这两位都是端到端测试界的扛把子,各有千秋。

特性 Cypress Playwright
运行环境 只能在浏览器中运行,基于 Node.js 可以跨浏览器运行(Chromium, Firefox, WebKit),支持 Node.js, Python, .NET, Java
API 友好度 API 设计简洁,易于上手,学习曲线平缓 API 相对复杂,但功能更强大,灵活性更高
调试体验 调试体验极佳,可以 time-traveling 调试,查看每一步操作的快照 调试工具强大,支持录制操作,生成测试代码
社区活跃度 社区庞大,资料丰富,容易找到解决方案 社区发展迅速,文档完善
隔离性 与应用运行在同一个进程中,可以访问应用的代码 与应用运行在不同的进程中,隔离性更好
跨域问题 默认情况下,Cypress 会处理跨域问题,无需额外配置 需要进行额外配置才能处理跨域问题
是否支持 Shadow DOM 支持有限,可能需要额外的配置 原生支持 Shadow DOM
适用场景 中小型项目,对调试体验要求高的项目,对跨浏览器兼容性要求不高的项目 大型项目,对跨浏览器兼容性要求高的项目,对隔离性要求高的项目

好,了解了基本概念,咱们开始实战!

第一步:搭建环境

假设你已经有一个Vue项目,如果没有,用Vue CLI快速创建一个:

vue create my-vue-app
cd my-vue-app

然后,安装Cypress或Playwright。

安装Cypress:

npm install cypress --save-dev
# 或者
yarn add cypress --dev

安装Playwright:

npm install -D @playwright/test
# 或者
yarn add -D @playwright/test

# 安装浏览器驱动 (可选,推荐)
npx playwright install

第二步:配置测试

Cypress:

安装完Cypress后,运行 npx cypress open,Cypress会打开一个图形界面,并自动生成一个 cypress 文件夹,里面包含了示例测试文件和其他配置。

  • cypress.config.js:Cypress 的配置文件,可以在这里设置baseUrl、viewport 等。
  • cypress/integration:存放测试文件的目录。
  • cypress/support:存放支持文件,例如自定义命令、全局配置等。
  • cypress/plugins:存放插件,可以扩展 Cypress 的功能。

修改 cypress.config.js,设置 baseUrl 为你的 Vue 应用的地址:

const { defineConfig } = require("cypress");

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:8080', // 替换为你的 Vue 应用地址
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
  },
});

Playwright:

Playwright 的配置稍微复杂一点。它会生成一个 playwright.config.ts 文件。

import { defineConfig, devices } from '@playwright/test';

/**
 * Read environment variables from file.
 * https://github.com/motdotla/dotenv
 */
// require('dotenv').config();

/**
 * See https://playwright.dev/docs/test-configuration.
 */
export default defineConfig({
  testDir: './tests', // 测试文件目录
  /* Run tests in files in parallel */
  fullyParallel: true,
  /* Fail the build on CI if you accidentally left test.only in the code. */
  forbidOnly: !!process.env.CI,
  /* Retry on CI only */
  retries: process.env.CI ? 2 : 0,
  /* Opt out of parallel tests on CI. */
  workers: process.env.CI ? 1 : undefined,
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
  reporter: 'html',
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
  use: {
    /* Base URL to use in actions like `await page.goto('/')`. */
    baseURL: 'http://localhost:8080', // 替换为你的 Vue 应用地址

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
  },

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },

    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },

    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },

    /* Test against mobile viewports. */
    // {
    //   name: 'Mobile Chrome',
    //   use: { ...devices['Pixel 5'] },
    // },
    // {
    //   name: 'Mobile Safari',
    //   use: { ...devices['iPhone 12'] },
    // },

    /* Test against branded browsers. */
    // {
    //   name: 'Microsoft Edge',
    //   use: { ...devices['Desktop Edge'], channel: 'msedge' },
    // },
    // {
    //   name: 'Google Chrome',
    //   use: { ...devices['Desktop Chrome'], channel: 'chrome' },
    // },
  ],

  /* Run your local dev server before starting the tests */
  // webServer: {
  //   command: 'npm run start',
  //   url: 'http://127.0.0.1:3000',
  //   reuseExistingServer: !process.env.CI,
  // },
});

同样,修改 baseURL 为你的Vue应用地址。

第三步:编写测试用例

Cypress:

cypress/integration 目录下创建一个新的测试文件,例如 example.spec.js

describe('My First Test', () => {
  it('Visits the app root url', () => {
    cy.visit('/') // 访问 baseUrl
    cy.contains('h1', 'Welcome to Your Vue.js App') // 验证页面内容
  })

  it('Navigate to About page', () => {
    cy.visit('/')
    cy.contains('a', 'About').click() // 点击 About 链接
    cy.url().should('include', '/about') // 验证 URL 是否包含 /about
    cy.contains('h1', 'This is an about page') // 验证页面内容
  })
})

这段代码做了两件事:

  1. 访问应用根目录 /,验证页面是否包含 <h1> 标签,内容为 "Welcome to Your Vue.js App"。
  2. 点击 "About" 链接,验证 URL 是否包含 /about,以及页面是否包含 <h1> 标签,内容为 "This is an about page"。

Playwright:

tests 目录下创建一个新的测试文件,例如 example.spec.ts

import { test, expect } from '@playwright/test';

test('Visits the app root url', async ({ page }) => {
  await page.goto('/'); // 访问 baseURL
  await expect(page.locator('h1')).toContainText('Welcome to Your Vue.js App'); // 验证页面内容
});

test('Navigate to About page', async ({ page }) => {
  await page.goto('/');
  await page.locator('a:has-text("About")').click(); // 点击 About 链接
  await expect(page).toHaveURL(/about/); // 验证 URL 是否包含 /about
  await expect(page.locator('h1')).toContainText('This is an about page'); // 验证页面内容
});

这段代码和Cypress的代码功能类似,只是API略有不同。

第四步:运行测试

Cypress:

运行 npx cypress open,Cypress 会打开图形界面,点击测试文件 example.spec.js 就可以运行测试了。 你也可以使用命令行运行: npx cypress run

Playwright:

运行 npx playwright test,Playwright 会运行所有测试文件。 你也可以指定运行某个文件:npx playwright test example.spec.ts

进阶技巧:更复杂的场景

上面只是简单的例子,实际项目中,我们需要处理更复杂的场景,比如:

  • 表单提交: 模拟用户输入数据,点击提交按钮,验证数据是否正确保存。
  • 异步请求: 等待异步请求完成,验证数据是否正确渲染。
  • 组件交互: 模拟用户与组件的交互,例如点击按钮,弹出对话框,选择选项等。
  • 登录认证: 模拟用户登录,验证是否成功跳转到登录后的页面。

Cypress:

// 表单提交
it('Submits the form', () => {
  cy.visit('/login')
  cy.get('input[name="username"]').type('testuser')
  cy.get('input[name="password"]').type('password123')
  cy.get('button[type="submit"]').click()
  cy.url().should('include', '/dashboard')
})

// 异步请求 (使用 cy.intercept 模拟 API 请求)
it('Loads data from API', () => {
  cy.intercept('GET', '/api/data', { fixture: 'data.json' }).as('getData') // 模拟 API 请求
  cy.visit('/data')
  cy.wait('@getData') // 等待 API 请求完成
  cy.contains('h2', 'Data from API')
})

// 自定义命令
Cypress.Commands.add('login', (username, password) => {
  cy.visit('/login')
  cy.get('input[name="username"]').type(username)
  cy.get('input[name="password"]').type(password)
  cy.get('button[type="submit"]').click()
  cy.url().should('include', '/dashboard')
})

it('Logs in with custom command', () => {
  cy.login('testuser', 'password123')
})

Playwright:

// 表单提交
test('Submits the form', async ({ page }) => {
  await page.goto('/login');
  await page.locator('input[name="username"]').fill('testuser');
  await page.locator('input[name="password"]').fill('password123');
  await page.locator('button[type="submit"]').click();
  await expect(page).toHaveURL(/dashboard/);
});

// 异步请求 (使用 page.route 模拟 API 请求)
test('Loads data from API', async ({ page }) => {
  await page.route('/api/data', async route => {
    await route.fulfill({ path: 'tests/fixtures/data.json' }); // 模拟 API 响应
  });
  await page.goto('/data');
  await expect(page.locator('h2')).toContainText('Data from API');
});

// 使用 Page Object Model
class LoginPage {
  constructor(public page: Page) {}

  async goto() {
    await this.page.goto('/login');
  }

  async login(username: string, password: string) {
    await this.page.locator('input[name="username"]').fill(username);
    await this.page.locator('input[name="password"]').fill(password);
    await this.page.locator('button[type="submit"]').click();
  }
}

test('Logs in with Page Object Model', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login('testuser', 'password123');
  await expect(page).toHaveURL(/dashboard/);
});

一些建议:

  • 使用 Page Object Model: 将页面元素和操作封装成类,提高代码的可维护性。
  • 编写清晰的测试用例: 测试用例应该易于理解,命名清晰,方便排查问题。
  • 充分利用测试工具提供的功能: 例如 Cypress 的 time-traveling 调试,Playwright 的录制功能。
  • 持续集成: 将端到端测试集成到 CI/CD 流程中,每次代码提交后自动运行测试。

最后,总结一下:

Cypress 和 Playwright 都是强大的端到端测试工具,可以帮助我们保证 Vue 应用的质量。选择哪个工具,取决于你的项目需求和团队的技术栈。

  • Cypress: 易于上手,调试体验好,适合中小型项目。
  • Playwright: 功能强大,支持跨浏览器,适合大型项目。

希望今天的分享能帮助大家更好地进行 Vue 应用的端到端测试。 记住,测试不是负担,而是保障! 祝大家写出高质量的代码,远离Bug!

发表回复

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