前言

本文面向前端/测试新手,系统讲解常见测试类型、测试金字塔、每种测试的优缺点、适用范围、使用场景,并搭配 Vue 可运行代码示例,帮助你真正理解“什么时候测、测什么、怎么测”。


目录

  1. 测试金字塔模型
  2. 核心测试类型详解(含优缺点 + 适用范围 + 示例)
  3. 补充测试类型
  4. 测试选型指南:什么场景用什么测试
  5. 总结

1. 测试金字塔模型

测试金字塔是行业通用的测试投入与优先级指导模型:

从上到下三层:

  1. UI / E2E 层(顶层)
    测试完整业务流程,贴近用户,但慢、贵、脆弱
  2. 集成 / 组件层(中间层)
    测试模块协作、组件交互,速度与稳定性均衡
  3. 单元测试层(底层)
    测试最小代码单元,最快、最稳、最便宜

核心原则:

  • 底层测试写越多越好
  • 上层测试写精而少
  • 越往下,Bug 发现越早,修复成本越低

2. 核心测试类型详解

2.1 单元测试(unit)

定义

单个函数、方法、工具类进行独立、隔离的测试,不依赖任何外部模块。

优点

  • 执行极快,毫秒级
  • 定位 Bug 精准
  • 可反复运行,非常稳定
  • 能驱动代码更模块化、更易维护

缺点

  • 只能保证代码逻辑正确,不能保证业务流程正确
  • 对复杂业务流程覆盖不足

使用范围

  • 工具函数
  • 表单校验
  • 计算逻辑
  • 数据转换、格式化

什么时候推荐使用

  • 公共工具方法
  • 逻辑复杂、容易出错的纯函数
  • 需要保证长期稳定的基础代码

Vue 代码示例(手机号校验)

// src/utils/validate.js
export function checkPhone(phone) {
  if (!phone) return false
  const reg = /^1[3-9]\d{9}$/
  return reg.test(phone)
}

// tests/unit/validate.test.js
import { checkPhone } from '@/utils/validate'
import { test, expect } from 'vitest'

test('正确手机号返回 true', () => {
  expect(checkPhone('13800001111')).toBe(true)
})

test('位数不足返回 false', () => {
  expect(checkPhone('1380000')).toBe(false)
})

test('空值返回 false', () => {
  expect(checkPhone('')).toBe(false)
})

2.2 组件测试(component)

定义

对 Vue 单个组件进行渲染、props、事件、插槽、展示逻辑测试。

优点

  • 速度快,比 E2E 快 10~100 倍
  • 能覆盖视图逻辑(v-if、v-for、点击、输入等)
  • 比单元测试更贴近真实使用场景

缺点

  • 不能测试跨页面、跨路由流程
  • 对复杂联动业务覆盖有限

使用范围

  • 按钮、表单、表格、弹窗等基础组件
  • 业务组件(登录表单、搜索框、卡片等)

什么时候推荐使用

  • 公共 UI 组件库
  • 复用次数多的业务组件
  • 视图逻辑复杂的组件

Vue 示例

// src/components/MyButton.vue
<template>
  <button @click="$emit('click')">
    {{ text }}
  </button>
</template>

<script setup>
defineProps(['text'])
defineEmits(['click'])
</script>
// tests/component/MyButton.test.js
import { mount } from '@vue/test-utils'
import { test, expect } from 'vitest'
import MyButton from '@/components/MyButton.vue'

test('组件显示正确文本并触发点击事件', async () => {
  const wrapper = mount(MyButton, {
    props: { text: '提交' }
  })

  // 检查渲染内容
  expect(wrapper.text()).toContain('提交')

  // 模拟点击
  await wrapper.find('button').trigger('click')

  // 检查事件是否触发
  expect(wrapper.emitted('click')).toBeTruthy()
})

2.3 组件测试固件(componentFixtures)

定义

为组件测试提前封装好固定数据、固定环境、固定挂载方式,避免每个测试重复写配置。

优点

  • 测试代码更简洁
  • 环境统一,测试更稳定
  • 便于维护,改一处即可全局生效

缺点

  • 增加一层封装,新手需要理解成本

使用范围

  • 多个测试用到同一个组件
  • 测试需要固定 mock 数据
  • 大型项目组件标准化测试

什么时候推荐使用

  • 项目中大量复用同类组件测试
  • 希望统一风格、减少重复代码

示例

// tests/fixtures/tableFixture.js
import { mount } from '@vue/test-utils'
import Table from '@/components/Table.vue'

export function createTableFixture() {
  const mockData = [
    { id: 1, name: '测试1' },
    { id: 2, name: '测试2' }
  ]

  const wrapper = mount(Table, {
    props: { data: mockData }
  })

  return { wrapper, mockData }
}

// 测试中使用
import { test, expect } from 'vitest'
import { createTableFixture } from '../fixtures/tableFixture'

test('表格正确渲染行数', () => {
  const { wrapper, mockData } = createTableFixture()
  expect(wrapper.findAll('tr')).toHaveLength(mockData.length)
})

2.4 集成测试(integration)

定义

测试多个模块协作是否正常,如:接口组合、函数调用链、Pinia + 业务逻辑、API 联调等。

优点

  • 能发现模块间接口问题
  • 比 E2E 快,比单元测试更贴近真实流程
  • 覆盖核心业务链路

缺点

  • 配置比单元测试复杂
  • 涉及异步逻辑时稍难编写

使用范围

  • 多函数协作逻辑
  • API 组合调用(登录 → 获取用户信息)
  • Pinia/Vuex 状态管理 + 业务逻辑

什么时候推荐使用

  • 模块之间依赖较强
  • 核心业务流程(购物车、下单、支付)

示例

// 模拟两个 API 模块
async function login() {
  return { token: 'mock-token' }
}

async function getUserInfo(token) {
  if (token) return { name: '张三' }
  return null
}

// 集成测试:测试两个接口协作
test('登录后可获取用户信息', async () => {
  const { token } = await login()
  const user = await getUserInfo(token)
  expect(user.name).toBe('张三')
})

2.5 冒烟测试(smoke test)

定义

构建/发版后,快速验证核心流程是否可用,只测最关键路径。

优点

  • 耗时极短(几分钟)
  • 快速挡掉不可用版本
  • 避免测试资源浪费

缺点

  • 覆盖极少,只保证“能跑”
  • 不深入细节

使用范围

  • 构建后验收
  • 提测前快速校验
  • 上线前预检

什么时候推荐使用

  • 每次打包/部署后
  • 修复后快速确认系统没崩

典型用例

1. 页面能否正常打开,不白屏
2. 能否正常登录
3. 能否进入首页
4. 接口是否可正常调用

2.6 健全性测试(sanity test)

定义

修复 Bug 或改功能后,只测相关影响范围,验证问题是否解决。

优点

  • 极精准、耗时短
  • 防止旧 Bug 重现
  • 防止引入新 Bug

缺点

  • 覆盖范围小,不做全量校验

使用范围

  • 小范围 Bug 修复
  • 局部功能优化
  • 快速回归

什么时候推荐使用

  • 改了登录页 → 只测登录
  • 改了价格计算 → 只测价格

与冒烟区别

  • 冒烟:看整体能不能跑
  • 健全性:看某一处修没修好

2.7 自动化测试(automation)

定义

用代码/工具自动执行测试,包括:单元、组件、集成、E2E 自动化。

优点

  • 一次编写,多次运行
  • 回归效率极高
  • 减少人工重复劳动

缺点

  • 初期编写成本高
  • 页面频繁变动时维护成本高

使用范围

  • 回归测试
  • 核心流程
  • 跨版本迭代

什么时候推荐使用

  • 项目长期维护
  • 需求稳定、不频繁大改
  • 多人协作项目

Vue E2E 示例(Playwright 简化)

test('自动登录系统', async ({ page }) => {
  await page.goto('http://localhost:5173')
  await page.fill('#username', 'admin')
  await page.fill('#password', '123456')
  await page.click('button[type="submit"]')
  await expect(page.locator('.user-name')).toContainText('admin')
})

2.8 Monaco 编辑器测试

定义

针对 Monaco 代码编辑器(VSCode 内核)的功能测试。

优点

  • 保障在线编辑器功能稳定
  • 可自动化校验语法、提示、事件

缺点

  • 环境依赖重
  • 只适用于带代码编辑器的项目

使用范围

  • 在线 IDE
  • 配置平台、代码编辑平台

什么时候推荐使用

  • Vue 项目中使用了 monaco-editor

2.9 MCP 测试

定义

Model Context Protocol,AI 大模型与测试工具结合的智能测试

优点

  • 自然语言生成测试
  • 降低自动化门槛
  • 智能探索场景

缺点

  • 仍处于发展阶段
  • 复杂场景稳定性一般

使用范围

  • AI 辅助测试
  • 快速生成用例
  • 简单 UI 流程自动化

3. 补充测试类型

3.1 E2E 端到端测试

优点

  • 最贴近真实用户
  • 覆盖完整业务链路

缺点

  • 慢、不稳定、易受环境影响

适用场景

  • 核心支付流程
  • 登录、下单、退款等关键链路

3.2 回归测试

优点

  • 防止改出新 Bug
  • 保证历史功能稳定

适用场景

  • 每次发版前
  • 每次改代码后

3.3 性能测试

测加载速度、并发、响应时间。
适合:首页、大量数据页面、高并发页面。

3.4 安全测试

测 XSS、CSRF、越权、SQL 注入。
适合:管理后台、登录、支付、用户中心。

3.5 兼容性测试

测不同浏览器、不同设备表现。
适合:面向 C 端的 Vue 项目。


4. 测试选型指南(新手直接照抄)

4.1 优先写:单元测试

  • 工具函数
  • 计算逻辑
  • 表单校验
  • 任何纯 JS 逻辑

4.2 其次写:组件测试

  • Vue 组件
  • 弹窗、表单、表格
  • 复用高的 UI 组件

4.3 然后写:集成测试

  • 多模块协作
  • API 调用链
  • Pinia / 状态逻辑

4.4 少量写:E2E 测试

  • 核心登录、下单、支付
  • 不超过全部用例的 10%

4.5 每次发版必须:冒烟测试

  • 5 分钟判断版本是否可用

4.6 每次改 Bug 必须:健全性测试

  • 精准验证修复点

5. 总结

  • 单元测试:最快最稳,优先写
  • 组件测试:Vue 前端核心测试
  • 集成测试:保证模块协作正常
  • 冒烟/健全性:快速校验,提测必备
  • E2E:只测核心流程
  • 自动化:长期项目必上

一个健康的 Vue 项目测试结构:
大量单元 + 适量组件/集成 + 少量 E2E

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐