Kotlin回归测试概述

回归测试,说白了就是「改完代码再跑一遍所有测试,确保没把老功能搞坏」。我刚开始接触Android项目时,总觉得回归测试浪费时间,心想「我就改了一行日志,不至于炸吧?」结果那次把支付模块的签名校验给误删了,提测后整个交易流程挂掉……嗯,从那以后我再也不敢忽视回归测试了。

回归测试的意义——为什么我们离不开它

你的项目迭代越快,改动面越大,回归测试的价值就越明显。它解决的核心问题只有一个:在持续集成和持续交付中,快速验证旧功能没有被新代码破坏。

  • 避免回归缺陷:你改A模块,B模块被间接影响了——这种情况几乎每天都在发生。
  • 降低修改成本:越早发现回归问题,修复成本越低。上线后再回滚,成本至少翻10倍。
  • 给重构底气:没有回归测试支撑的重构,跟裸奔没什么区别。
  • 提升团队信心:每次提交都能一键跑过回归用例,大家才敢放心合代码。

我个人的经验:以前做金融SDK,每次对接新的加密算法,我都会写一套回归测试套件,覆盖所有历史业务场景。哪怕新算法性能再好,回归没过我绝不合并。有一次正是因为回归测试发现了旧签名长度限制被改小,才避免了一次线上事故。

回归测试的常见类型

类型 范围 执行频率 适用场景
全量回归 整个项目测试用例 发布前 / 大重构后 版本大迭代、底层架构变更
增量回归 改动模块及关联模块 每次提交 日常开发、紧急热修复
冒烟回归 核心业务流程(20%) 每日构建 快速验证可用性,确认主干未断

你想想看,如果每次改几行都要跑全量测试,开发效率肯定受不了。所以大多数团队会采用「增量回归为主 + 冒烟回归保底 + 全量回归兜底」的组合策略。

kotlin.test 库概览——Kotlin原生测试框架

提到Kotlin回归测试,你可能会先想到JUnit或TestNG。但Kotlin官方还提供了一个轻量但功能完备的测试库——kotlin.test。它直接集成在标准库中,无需额外依赖,语法更接近Kotlin惯用写法。

kotlin.test 的核心能力包括:

  • 断言函数:assertEquals、assertTrue、assertNotNull 等,比Java的JUnit断言更简化。
  • 注解支持:@Test、@BeforeTest、@AfterTest,与JUnit 5风格类似但更原生。
  • 期望异常:assertFailsWith 直观捕获特定异常。
  • 忽略测试:@Ignore 标注暂时不跑的用例。
  • 测试分组:通过 @Tag 注解对用例分类,方便只跑特定子集。

小提示:kotlin.test 底层实际上是包装了JUnit平台。所以你可以在同一个项目里同时使用JUnit 5的高级特性和kotlin.test的简洁语法,两者互补。

看一个简单的回归测试例子

假设我们有一个计算折扣的函数,我们需要写一个回归测试来确保后续改动不会破坏原有逻辑。

// 目标函数:根据原价和会员等级计算折后价
fun calculateDiscount(price: Double, level: String): Double {
    return when (level) {
        "vip" -> price * 0.8
        "svip" -> price * 0.65
        else -> price
    }
}

对应的回归测试用例:

import kotlin.test.*

class DiscountTest {
    @Test
    fun `普通用户无折扣`() {
        val result = calculateDiscount(100.0, "normal")
        assertEquals(100.0, result)
    }

    @Test
    fun `VIP用户打8折`() {
        val result = calculateDiscount(100.0, "vip")
        assertEquals(80.0, result)
    }

    @Test
    fun `SVIP用户打65折`() {
        val result = calculateDiscount(100.0, "svip")
        assertEquals(65.0, result)
    }
}

这三个测试覆盖了所有分支。如果有人把折扣逻辑改成了「SVIP打6折」而忘记同步,第二个用例就会立刻失败——这就是回归测试的价值。

我曾经踩过的坑:一开始我习惯把所有断言写在一个@Test方法里,一旦前面的断言失败整个方法就跳出了,后面的回归场景根本测不到。后来我改成每个场景一个独立的@Test方法,这样即使某个场景失败,其他场景依然可以运行——排错效率高很多。

知识体系:Kotlin回归测试核心框架

下面这张图梳理了回归测试和kotlin.test库的关系。你可以把它作为章节地图,后面所有的技巧都会围绕着几个核心节点展开。

Kotlin回归测试知识核心 Kotlin 回归测试 回归测试的意义 避免回归缺陷 降低修改成本 提升重构信心 kotlin.test 库 断言函数 注解支持 测试运行器 持续集成 + 自动化回归 增量&全量&冒烟策略 轻量原生,与JUnit兼容

什么时候该把回归测试纳入流程?

我认为有一条比较实用的判断标准:当你的项目有了3个以上开发者,或者迭代周期短于1周时,手动回归就已经不可靠了。这时候需要开始建立自动化的回归测试体系,而kotlin.test就是零成本起步的选择。

另外,如果你的项目使用了Gradle多模块构建,可以在每个模块下都建一个src/test/kotlin目录,按模块粒度组织回归测试。跑的时候用./gradlew test --tests "*.DiscountTest"就能只跑指定用例,非常方便。

总结一下本章核心要点:

  • 回归测试的价值在于「快速发现改坏的老功能」。
  • 三种策略(全量/增量/冒烟)各有适用场景,实际项目中混合使用。
  • kotlin.test 是 Kotlin 官方原生测试库,语法简洁,可直接用于回归测试。
  • 在 CI/CD 中接入 kotlin.test,每次提交自动运行回归用例,是防止退化的最佳实践。