回归测试是什么?我的理解

先聊个我踩过的坑。几年前维护一个Kotlin写的后端服务,每次加新功能都只测新增的接口。某个周五改了个工具类里的空指针判断,结果周一线上挂了一片——依赖这个工具类的十几个老接口全炸了。那之后我才真正意识到:回归测试不是锦上添花,是项目的刹车片。

说白了,回归测试就是每次代码变动后,把老功能重新跑一遍。你不用每次手动点,写个自动化测试就行。在Kotlin生态里,官方提供的kotlin.test库就是干这个的。

定义:别把回归测试想得太复杂

回归测试的核心就一句话:保证改过代码后,以前能跑的还能跑。它不关心新功能的正确性(那是功能测试的事),而是盯着旧功能有没有被无意破坏。

举个例子:你重构了某个类的异步协程逻辑,回归测试会检查原来的同步调用、异常处理、数据一致性是否依然正常。我把它叫作“安”。你想想看,没有这张网,谁敢在线上频繁发布?

回归测试 ≠ 全部重测 我们不是把上千个用例全跑一遍。好的回归测试是“精准打击”——只验证受到变更影响的模块和边界。

目的:我们为什么要做回归测试?

  • 捕捉增量风险:小改动可能引发大问题,尤其是公共模块、基类、扩展函数这些“牵一发动全身”的地方。
  • 加速迭代节奏:有回归测试保驾护航,你才敢大胆重构。我记得有个项目,加回归测试后发布频率从两周一次变成一天三次。
  • 沉淀测试资产:每次发现的bug,补一个回归用例,项目就能越来越稳。说白了,测试用例就是项目的“免疫疫苗”。

重要性:没有回归测试,项目迟早翻车

我曾经在接手一个老项目时,发现一个线上bug改了三周——因为每次改完,总会有新的地方崩掉。后来我和团队花了三天补了一百多个回归用例,之后同样的改动只需半天。

回归测试的重要性可以用表格对比说明:

维度 有回归测试 无回归测试
代码变更信心 高,push前跑一遍就知道是否安全 低,改一行代码都要手动点所有关联页面
上线错误率 通常 < 2% 可能达到 10%~30%
新人上手速度 快,回归用例就是活文档 慢,全靠口口相传
维护成本 前期投入,后期节省大量排查时间 后期被动增加,每次出bug都要从头查

你看到差距了吧?有人觉得写测试浪费时间,其实恰恰相反——写过一次,后续每一版都能白嫖那个“安”。

Kotlin回归测试核心流程 代码变更 (Commit/Push) 触发回归测试套件 基础功能验证 冒烟测试 / 核心业务路径 边界条件检查 空值 / 异常 / 极端输入 增量代码覆盖 变更代码行+受影响调用链 质量门禁检查 全部通过?失败? ✅ 通过 → 合入 ❌ 失败 → 回退 持续集成流水线中自动触发,反馈时间 < 5 分钟 △ 三个测试维度

在Kotlin中使用回归测试:一个极简例子

你不用等全部写好再跑。比如我们有个计算订单总额的方法:

// 业务代码
fun calculateTotal(items: List<Item>): Double {
    return items.sumOf { it.price * it.quantity * (1 - it.discount) }
}

// 回归测试(使用kotlin.test)
class OrderTest {
    @Test
    fun `回归验证:空列表应返回0`() {
        val result = calculateTotal(emptyList())
        assertEquals(0.0, result, 0.001)
    }
    
    @Test
    fun `回归验证:折扣不影响总额为负数的情况`() {
        val items = listOf(Item(price = 100.0, quantity = 2, discount = 1.2))
        val result = calculateTotal(items)
        assertTrue(result < 0) // 以前支持负折扣?这里回归抓到了不一致
    }
}

看到没?第二个测试就抓住了潜在问题——折扣超过100%时结果是负数,业务上可能不应该允许。回归测试帮你在小范围里发现这类“意想不到的涟漪”。

习惯建议:我习惯在每次功能开发前,先把涉及到的旧功能回归用例拉一遍。这样改完代码后只需要执行./gradlew test就能看到有没有“震到”老代码。

避坑指南

我曾经犯过三个典型错误,你注意避开:

  1. 只测新增,不测旧功能——这就是开篇那个线上故障的根源。记住:回归测试不是单元测试的附属,它是独立的质量门禁。
  2. 回归用例写得太“脆”——比如依赖具体时间戳、随机UUID、Mock固定返回值。这种用例经常误报,反而让人忽视真正的问题。
  3. 等到CI才跑回归——本地提交前跑一遍,能节省你半小时排队等CI结果的时间。

警告:不要滥用回归测试 并不是所有旧代码都需要回归。只对“核心公共模块”和“频繁变更区域”维护回归用例。否则测试维护成本会反噬项目。

现在你该做什么?

看完这章,我建议你打开一个现有的Kotlin项目:

  • 找到至少一个曾经出过bug的核心函数,给它写一个简单的回归测试(用@Test和assertEquals)。
  • 然后故意改错一行代码,跑一下测试,感受“安”的存在。