第1章:为什么要做测试?——一个让我翻过车的教训

说实话,我刚开始做Android开发那几年,对测试这件事是有点不屑的。总觉得「代码我写的,能跑就行」。直到有一次,我负责的一个电商App上线后,用户在支付页面疯狂闪退——原因居然是一个简单的空指针,而那个分支我压根没测到。

那天晚上我盯着崩溃日志,心里只有一个念头:如果当初写了测试,这锅根本不用背

所以这一章,我想跟你聊聊测试的意义。不是讲大道理,而是用我踩过的坑,帮你少走弯路。

1.1 测试到底解决了什么问题?

你想想看,一个App从开发到上线,最怕什么?

  • 改一个功能,炸了三个旧功能——回归测试全靠人肉点,点漏了就出事
  • 线上崩溃,定位半天找不到原因——日志不全,复现不了
  • 团队协作,你改你的我改我的——合并完直接编译不过

测试,说白了就是给代码上「保险」。它不能保证100%没bug,但能让你有信心去改代码、去重构、去上线。

核心观点:测试不是「额外工作」,而是「效率投资」。你花1小时写测试,可能省下未来10小时的排查时间。

1.2 测试金字塔:你应该把精力花在哪?

我记得刚接触测试时,看到一张经典的「测试金字塔」图,瞬间就明白了测试的分层逻辑。这里我用SVG画出来,方便你理解。

UI测试 少而精 覆盖核心用户流程 集成测试 适量 验证模块间交互 单元测试 多而快 覆盖每个函数/类 测试数量 测试速度

这张图告诉我们三件事:

  1. 单元测试要最多——它跑得快,能覆盖各种边界情况
  2. UI测试要最少——它跑得慢,还容易受环境干扰
  3. 集成测试居中——用来验证模块之间有没有「打架」

我的经验:我习惯把70%的精力放在单元测试上,20%给集成测试,10%给UI测试。这个比例不是绝对的,但如果你UI测试写了一大堆,单元测试却没几个,那大概率是方向错了。

1.3 Kotlin给测试带来了什么?

如果你用过Java写测试,再切到Kotlin,你会觉得——真香

Kotlin有几个特性,让测试代码写起来特别舒服:

特性 对测试的帮助
空安全 减少NPE,测试不用写一堆null判断
扩展函数 可以给测试框架加自定义断言
数据类 自动生成equals/hashCode,断言更方便
协程 测试异步代码变得简单

举个例子,在Java里你要测试一个异步回调,得用CountDownLatch或者等回调。但在Kotlin里,配合协程测试,代码可以写成这样:

// 假设有一个 suspend 函数
suspend fun fetchUser(): User {
    return api.getUser()
}

// 测试代码
@Test
fun `test fetchUser returns correct name`() = runTest {
    val user = fetchUser()
    assertEquals("Alice", user.name)
}

你看,runTest直接把异步变成了同步,测试逻辑一目了然。这在Java里得写一堆样板代码。

注意:协程测试虽然方便,但要注意runTest的调度器行为。我曾经因为没搞清楚StandardTestDispatcherUnconfinedTestDispatcher的区别,导致测试在CI上一直超时。后面我会专门讲这个坑。

1.4 本课程你会学到什么?

这门课不是讲理论,而是手把手带你实战。从最简单的单元测试,到复杂的UI自动化测试,再到CI集成和质量门禁,我会把我在项目中积累的经验全部分享给你。

具体来说,你会掌握:

  • JUnit5 + MockK:写干净、可维护的单元测试
  • Compose UI测试:用Compose Test API验证界面行为
  • 依赖注入与测试:用Hilt/Dagger让测试更灵活
  • 测试覆盖率与质量门禁:让CI自动拦截低质量代码
  • 测试维护策略:如何让测试不变成「技术债务」

一句话总结:学完这门课,你不仅能写出高质量的测试,还能建立起一套可持续的测试体系。

1.5 写在开始之前

我知道,很多人觉得测试麻烦、浪费时间。我以前也这么想。但当你经历过线上事故、经历过通宵排查、经历过被用户骂到想删App的时候,你就会明白——测试不是负担,而是底气

这一章我们聊了测试的意义和整体框架。下一章,我会带你从零搭建一个测试项目,把工具链配好。嗯,到时候记得带上你的Android Studio。


公众号:蓝海资料掘金营,微信 deep3321