前端单元测试
2025-12-15 10:35:44

我寻思单元测试的必要性!能实现什么价值?怎么评估两种常见开发模式?

为什么强调单元测试的是敏捷开发而不是瀑布开发?

那么他们有什么区别呢?为什么提到它?🤔

瀑布模型

在传统的瀑布流开发模式中,通常要经历以下几个阶段:

1
分析 -> 设计 -> 开发 -> 测试

其工作流程是线性的,它将项目划分成一系列严格的阶段,每个阶段要审查验证完前一个阶段才会开始下一个阶段!这种模式有一个很大的缺陷,如果需求经常变动,或者交付完之后发现市场需求又有了变化,往往又要从新开始。

优点:流程清晰、易于管理,适合需求明确、技术成熟的产品。

缺点:灵活性差,如果后期需求变更或设计有问题,修改成本高昂;且客户往往需要在项目后期才能看到实际产品。

强调前期详细的文档和规划

敏捷开发

这是迭代的、基于团队的开发方法!将项目开发划分为多个小的迭代周期,每个迭代周期内,团队专注于完成一部分功能并交付可工作的的软件原型。通过持续的反馈以确保项目按照预期的方向去前进,且能够及时调整开发方向以满足变化的需求。

1
2
3
4
5
6
7
8
迭代周期一:
需求 -> loop(设计 -> 开发 -> 测试) -> 发布

迭代周期二:
需求 -> loop(设计 -> 开发 -> 测试) -> 发布

迭代周期三:
需求 -> loop(设计 -> 开发 -> 测试) -> 发布

项目团队和客户可以通过每个 loop 种对产品进行审查和评估,这样当我们产生变化的时候,我们推翻的工作量也是少量的,可以很快的去完成新的需求变更。通过这样的不断地变更、重构,我们可以获得一个相对客户满意的产品。

优点:快速适应需求变化,客户能在早期持续看到产品降低风险,在需求变化时团队能够迅速做出调整而无需改变项目计划。

缺点:对团队协作要求高,项目范围与成本难以预测,不适合需要大量前期设计的复杂系统。

强调客户的反馈、可工作的软件

测试

重构与单元测试的关系也是密不可分的,因为重构应是在不改变软件行为的情况下改善优化代码内部的设计与实现,而如何去保障这个前提,则是单元测试的用武之地。

当然!对于上面的软件行为情况,有条件的可以使用人工测试!但人工测试很大程度上依赖测试人员的水平及其对软件的了解程度,且人员是流动的并非一成不变,但软件的需求却是一定会累加,迭代久了就会出现没有人能够了解软件的全部行为功能,那么此时将是一个灾难,因为已经不能保证我们对软件的修改是稳定的!

拥有完备的单元测试才能自动化地对已有的功能跟新开发功能做到持续集成(CI)持续交付(CD)

// 自动化回归

端对端测试!集成测试!单元测试?

Something

敏捷开发与单元测试

敏捷开发要求”快速变化”,敏捷鼓励持续改进代码质量(重构),但快速变化最容易引入错误。单元测试正是解决这一矛盾的关键工具——让团队既能快速前进,又能保证质量。没有单元测试的敏捷开发,最终会因为技术债务和质量问题而失败。

快速迭代需要快速反馈

敏捷开发注重“拥抱变化”,需求与代码经常调整,如果依赖手工测试或者集成测试,反馈周期会拖慢整个迭代的节奏,而单元测试的运行及编写成本极低,能够进行立即验证!

频繁变更需要安全保障

敏捷开发是一种拥抱变化的开发方式,需求与代码经常调整,没有单元测试每次修改都有可能引入隐藏的 Bug(回归问题)。单元测试则是一个安全保障,保证修改不会破坏原有功能。而敏捷开发也是一个强调团队的方式,单元测试让团队成员敢于修改不熟悉的代码,避免**”只有原作者才敢动这段代码”**的困境。

因敏捷开发以短周期迭代的方式进行开发,其要求能够快速发现问题解决问题,

前端集成

社交型测试单元

独立型测试单元

Given-When-Then

它是一种结构化编写测试用例的方法,特别常用于行为驱动开发(BDD)和单元测试中。它将测试分为三个清晰的部分,其优点如下:

  • 可读性强: 测试意图一目了然
  • 结构清晰: 强制分离准备、执行、验证
  • 易于维护: 降低测试代码的复杂度
  • 沟通友好: 非技术人员也能理解测试场景

Given

给定/准备阶段

  • 设置测试的初始状态和前置条件
  • 准备测试数据、mock 对象、初始化依赖等
  • 回答:”在什么样的场景下?”

When

当/执行阶段

  • 执行被测试的操作或行为
  • 通常是调用某个方法或触发某个事件
  • 回答:”做了什么?”

Then

那么/断言阶段

  • 验证期望的结果
  • 使用断言检查输出、状态变化或副作用
  • 回答:”应该得到什么结果?”

示例

python 例子

1
2
3
4
5
6
7
8
9
def test_withdraw_money_from_account():
# Given: 账户有100元余额
account = Account(balance=100)

# When: 取款50元
account.withdraw(50)

# Then: 余额应该是50元
assert account.balance == 50

JavaScript 例子

1
2
3
4
5
6
7
8
9
10
11
test('用户登录成功', () => {
// Given: 有一个有效的用户
const user = { username: 'test', password: 'pass123' }

// When: 用户尝试登录
const result = authService.login(user)

// Then: 应该返回成功和token
expect(result.success).toBe(true)
expect(result.token).toBeDefined()
})

React 实践

测试样例放在被测文件相同目录还是外部集合?

项目使用了 TypeScript 是否还需要测试无效类型?

Reference

维基百科-瀑布模型

维基百科-敏捷开发

瀑布式开发和敏捷开发的区别

Prev
2025-12-15 10:35:44
Next