1、.NET测试基础:为什么需要自动化测试、测试金字塔模型、单元测试与集成测试的区别、.NET测试生态概览
为什么我们需要自动化测试?
说实话,我见过太多项目在交付前一周陷入恐慌。开发人员熬夜改代码,测试人员疯狂点鼠标,项目经理在会议室里来回踱步。这种场景,我经历过不止一次。
自动化测试不是银弹,但它能解决一个核心问题:让代码变更变得安全。你想想看,当你重构一个方法时,怎么知道没把别的地方搞坏?手动跑一遍所有功能?不现实。自动化测试就像一张安全网,你改完代码,跑一遍测试,绿了,心里就有底了。
我个人习惯把自动化测试的价值总结为三点:
- 快速反馈——几秒钟告诉你代码有没有问题
- 回归保障——改旧代码时不怕引入新bug
- 文档即代码——测试用例本身就是最好的使用说明
核心观点:没有自动化测试的项目,本质上是在靠「人肉」做回归测试。人总会累、会漏、会出错。机器不会。
测试金字塔模型
这个概念我第一次听是在2015年,当时觉得不就是分层嘛,有啥好讲的。后来在项目中吃了亏才明白——金字塔的形状决定了你的测试策略是否健康。
测试金字塔分三层:
| 层级 | 类型 | 数量 | 速度 | 维护成本 |
|---|---|---|---|---|
| 顶层 | 端到端测试 | 少 | 慢 | 高 |
| 中间层 | 集成测试 | 适中 | 中等 | 中等 |
| 底层 | 单元测试 | 多 | 快 | 低 |
为什么底层要写最多?因为单元测试跑得快、定位准。我曾经在一个项目中看到团队写了大量端到端测试,结果每次CI跑测试要40分钟,而且一挂就是一大片,根本不知道哪里出了问题。这就是典型的「倒金字塔」——反模式。
我的建议:单元测试占比70%以上,集成测试20%,端到端测试10%以内。这个比例不是绝对的,但偏离太多就要警惕了。
单元测试与集成测试的区别
这个问题我面试时经常问。很多人能背出定义,但一到实际写代码就混淆。
单元测试——测试的是「一个单元」。在.NET里,通常是一个类的一个方法。它不依赖外部资源(数据库、文件系统、网络)。说白了,就是把你写的逻辑单独拎出来测。
集成测试——测试的是「多个单元协作」。比如一个Service调用了Repository,Repository又操作了数据库。这时候测的是它们能不能配合好。
举个例子:
// 单元测试:只测计算逻辑,不碰数据库
[Fact]
public void CalculateDiscount_WhenTotalOver100_ShouldReturn10Percent()
{
var service = new DiscountService();
var result = service.CalculateDiscount(150);
Assert.Equal(15, result);
}
// 集成测试:真的去查数据库
[Fact]
public async Task GetOrder_WhenOrderExists_ShouldReturnOrderFromDatabase()
{
// 这里需要真实的数据库连接
var repo = new OrderRepository(connectionString);
var order = await repo.GetByIdAsync(1);
Assert.NotNull(order);
}
注意:单元测试里不要连数据库。我见过有人把单元测试写成集成测试,结果测试跑得慢不说,还经常因为数据库连接失败而挂掉。这完全失去了单元测试的意义。
.NET测试生态概览
嗯,这里我简单梳理一下。.NET的测试生态其实挺成熟的,主要分三块:
- 测试框架:xUnit(我推荐)、NUnit、MSTest。xUnit是现在的主流,设计更现代,扩展性好。
- 模拟框架:Moq、NSubstitute、FakeItEasy。我个人习惯用Moq,社区活跃,文档全。
- 辅助工具:FluentAssertions(让断言更可读)、AutoFixture(自动生成测试数据)、Coverlet(覆盖率统计)。
还有一个不得不提的是Testcontainers。这个库可以在集成测试中启动Docker容器,比如测试需要SQL Server,直接拉一个镜像起来,测试完自动销毁。我在项目中用过,非常方便。
一句话总结:自动化测试不是可选项,是专业开发的标配。测试金字塔帮你规划策略,分清单元测试和集成测试让你少走弯路,.NET生态提供了足够好的工具。剩下的,就是动手写了。
下一章我会带你搭建第一个xUnit测试项目,咱们手把手来。到时候你会发现,写测试其实没那么难。