Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • E2E 测试:Cypress 入门

E2E 测试:Cypress 入门

端到端(E2E)测试是验证 Vue 3 应用整体功能的重要手段,模拟真实用户行为,确保从界面到后端的完整流程按预期运行。Cypress 是一款现代化的 E2E 测试框架,以其简单易用、强大的调试能力和实时反馈受到广泛欢迎。本节将介绍 Cypress 的基本概念、安装配置和使用方法,并通过示例展示如何为 Vue 3 项目编写 E2E 测试,帮助你快速入门并提升应用质量。

什么是 E2E 测试?

E2E 测试(End-to-End Testing)是对整个应用的集成测试,从用户视角验证功能是否正确。它不同于单元测试,关注的是应用的外部行为而非内部实现。

为什么选择 Cypress?

  • 简单易用:基于 JavaScript,API 直观。
  • 实时调试:内置浏览器界面,可视化测试过程。
  • 快照与时间旅行:记录每步状态,支持回溯。
  • 无需额外配置:开箱即用,支持 Vue 3 项目。

安装与配置

安装

在 Vue 3 项目中添加 Cypress:

npm install -D cypress

初始化

运行命令生成 Cypress 配置和示例文件:

npx cypress open
  • 生成结构:
    cypress/
    ├── e2e/              # 测试用例目录
    │   └── example.cy.js # 示例测试
    ├── support/          # 支持文件
    │   ├── commands.js
    │   └── e2e.js
    └── cypress.config.js # 配置文件
    

配置 cypress.config.js

// cypress.config.js
import { defineConfig } from 'cypress';

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:5173', // Vite 默认端口
    specPattern: 'cypress/e2e/**/*.cy.{js,ts}', // 测试文件模式
    setupNodeEvents(on, config) {
      // 自定义事件
    }
  }
});

package.json

{
  "scripts": {
    "test:e2e": "cypress open",
    "test:e2e:run": "cypress run"
  }
}

项目结构

src/
├── components/
│   └── Counter.vue
├── cypress/
│   ├── e2e/
│   │   └── counter.cy.js
│   └── cypress.config.js
├── vite.config.js
└── package.json

基本使用

测试组件:Counter.vue

<!-- src/components/Counter.vue -->
<template>
  <div>
    <p data-testid="count">计数: {{ count }}</p>
    <button data-testid="increment" @click="increment">增加</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    const count = ref(0);
    const increment = () => count.value++;
    return { count, increment };
  }
});
</script>

编写 E2E 测试

counter.cy.js

// cypress/e2e/counter.cy.js
describe('Counter Component', () => {
  beforeEach(() => {
    cy.visit('/'); // 访问根路径
  });

  it('displays initial count', () => {
    cy.get('[data-testid="count"]').should('have.text', '计数: 0');
  });

  it('increments count when button is clicked', () => {
    cy.get('[data-testid="increment"]').click();
    cy.get('[data-testid="count"]').should('have.text', '计数: 1');
  });

  it('increments multiple times', () => {
    cy.get('[data-testid="increment"]').click().click();
    cy.get('[data-testid="count"]').should('have.text', '计数: 2');
  });
});

运行测试

  1. 启动开发服务器:
    npm run dev
    
  2. 运行 Cypress:
    npm run test:e2e
    
    • 打开 Cypress 界面,选择 counter.cy.js 执行。
  • 效果:浏览器显示测试过程,验证计数器功能。

命令行运行

npm run test:e2e:run
  • 输出:终端显示测试结果。

核心测试技巧

1. 选择器与断言

  • 使用 data-testid:
    <p data-testid="count">{{ count }}</p>
    
    cy.get('[data-testid="count"]').should('contain', '计数: 0');
    
  • 断言:
    • should('have.text', 'value'):验证文本。
    • should('be.visible'):验证可见性。

2. 模拟用户交互

it('increments on button click', () => {
  cy.get('[data-testid="increment"]').click();
  cy.get('[data-testid="count"]').should('have.text', '计数: 1');
});

3. 测试异步行为

AsyncComp.vue

<template>
  <p data-testid="data">{{ data }}</p>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  async setup() {
    const data = ref('');
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
    data.value = (await response.json()).title;
    return { data };
  }
});
</script>

测试

// cypress/e2e/asyncComp.cy.js
describe('AsyncComp', () => {
  it('loads async data', () => {
    cy.visit('/');
    cy.get('[data-testid="data"]').should('not.be.empty');
    cy.get('[data-testid="data"]').should('contain', 'delectus aut autem');
  });
});

4. 测试路由导航

router/index.js

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/', component: () => import('@/components/Counter.vue') },
  { path: '/async', component: () => import('@/components/AsyncComp.vue') }
];

export default createRouter({
  history: createWebHistory(),
  routes
});

测试

it('navigates to async page', () => {
  cy.visit('/');
  cy.get('[data-testid="count"]').should('have.text', '计数: 0');
  cy.visit('/async');
  cy.get('[data-testid="data"]').should('contain', 'delectus aut autem');
});

高级技巧

1. 自定义命令

support/commands.js

Cypress.Commands.add('incrementCounter', () => {
  cy.get('[data-testid="increment"]').click();
});

使用

it('uses custom command', () => {
  cy.visit('/');
  cy.incrementCounter();
  cy.get('[data-testid="count"]').should('have.text', '计数: 1');
});

2. Mock API 请求

  • 拦截请求:
    it('mocks API response', () => {
      cy.intercept('GET', 'https://jsonplaceholder.typicode.com/todos/1', {
        statusCode: 200,
        body: { title: 'Mocked Title' }
      }).as('getTodo');
      cy.visit('/async');
      cy.wait('@getTodo');
      cy.get('[data-testid="data"]').should('contain', 'Mocked Title');
    });
    

3. 截图与视频

  • 自动记录:
    • 运行 cypress run 时生成视频(cypress/videos)。
  • 手动截图:
    it('takes screenshot', () => {
      cy.visit('/');
      cy.screenshot('home-page');
    });
    

注意事项

  1. 测试环境:
    • 确保开发服务器运行,避免端口冲突。
  2. 异步等待:
    • 使用 cy.wait() 或 .should() 确保状态稳定。
  3. 覆盖范围:
    • E2E 测试不需覆盖所有单元测试场景,聚焦关键流程。

整合到 CI

package.json

{
  "scripts": {
    "test:e2e:ci": "start-server-and-test 'vite' http://localhost:5173 'cypress run'"
  }
}
  • 安装依赖:
    npm install -D start-server-and-test
    

总结

Cypress 为 Vue 3 提供了简单高效的 E2E 测试方案,通过直观的 API 和强大的调试工具,你可以轻松验证应用的整体功能。本节介绍了安装配置、基本测试和高级技巧,下一节将探讨项目打包与部署,带你完成开发的最后一步!

Last Updated:: 2/24/25, 3:35 PM