第1章:为什么要做测试?——一个让我翻过车的教训
说实话,我刚开始做Android开发那几年,对测试这件事是有点不屑的。总觉得「代码我写的,能跑就行」。直到有一次,我负责的一个电商App上线后,用户在支付页面疯狂闪退——原因居然是一个简单的空指针,而那个分支我压根没测到。
那天晚上我盯着崩溃日志,心里只有一个念头:如果当初写了测试,这锅根本不用背。
所以这一章,我想跟你聊聊测试的意义。不是讲大道理,而是用我踩过的坑,帮你少走弯路。
1.1 测试到底解决了什么问题?
你想想看,一个App从开发到上线,最怕什么?
- 改一个功能,炸了三个旧功能——回归测试全靠人肉点,点漏了就出事
- 线上崩溃,定位半天找不到原因——日志不全,复现不了
- 团队协作,你改你的我改我的——合并完直接编译不过
测试,说白了就是给代码上「保险」。它不能保证100%没bug,但能让你有信心去改代码、去重构、去上线。
核心观点:测试不是「额外工作」,而是「效率投资」。你花1小时写测试,可能省下未来10小时的排查时间。
1.2 测试金字塔:你应该把精力花在哪?
我记得刚接触测试时,看到一张经典的「测试金字塔」图,瞬间就明白了测试的分层逻辑。这里我用SVG画出来,方便你理解。
这张图告诉我们三件事:
- 单元测试要最多——它跑得快,能覆盖各种边界情况
- UI测试要最少——它跑得慢,还容易受环境干扰
- 集成测试居中——用来验证模块之间有没有「打架」
我的经验:我习惯把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的调度器行为。我曾经因为没搞清楚StandardTestDispatcher和UnconfinedTestDispatcher的区别,导致测试在CI上一直超时。后面我会专门讲这个坑。
1.4 本课程你会学到什么?
这门课不是讲理论,而是手把手带你实战。从最简单的单元测试,到复杂的UI自动化测试,再到CI集成和质量门禁,我会把我在项目中积累的经验全部分享给你。
具体来说,你会掌握:
- JUnit5 + MockK:写干净、可维护的单元测试
- Compose UI测试:用Compose Test API验证界面行为
- 依赖注入与测试:用Hilt/Dagger让测试更灵活
- 测试覆盖率与质量门禁:让CI自动拦截低质量代码
- 测试维护策略:如何让测试不变成「技术债务」
一句话总结:学完这门课,你不仅能写出高质量的测试,还能建立起一套可持续的测试体系。
1.5 写在开始之前
我知道,很多人觉得测试麻烦、浪费时间。我以前也这么想。但当你经历过线上事故、经历过通宵排查、经历过被用户骂到想删App的时候,你就会明白——测试不是负担,而是底气。
这一章我们聊了测试的意义和整体框架。下一章,我会带你从零搭建一个测试项目,把工具链配好。嗯,到时候记得带上你的Android Studio。
公众号:蓝海资料掘金营,微信 deep3321