首页 / 资讯中心 / 文章详情

D22_行为测试与虚拟时间

D22_行为测试与虚拟时间 ★ FEATURED ARTICLE
Android 学习笔记 D22测试该验证什么从失败保留缓存到虚拟时间文章列表能打开不意味着数据链路已经可靠。真正容易回归的地方通常藏在异常路径里刷新失败清空了旧内容取消收藏只更新一个页面旧搜索结果覆盖新关键词。这一天先不追求覆盖率数字而是把四个已经承诺给用户的行为变成可以自动检查的约束。本文对应课程 D22。书籍的网络、存储与 Jetpack 内容提供被测试对象本篇的 Fake、协程测试和 Compose 测试属于工程实践拓展。示例是教学用的独立逻辑不代表 DevCommunity 已经具有这些测试。先把需求写成输入与输出“测试 Repository”太宽泛“当已有两篇文章且刷新失败仍然保留这两篇并显示错误”才是能执行的要求。先规定输出就不容易写出只验证某个函数调用次数、却遗漏用户实际结果的测试。场景初始条件需要断言的结果首次加载没有缓存成功得到文章或明确失败并能重试刷新失败已有文章原文章保留错误可见加载结束搜索乱序先 A 后 B最终结果属于 B取消收藏同 ID 出现在两个页面数据来源和两页展示一致纯转换函数适合本地测试数据库行为需要数据库夹具真正涉及点击与导航的行为再交给 UI 测试。选择工具是为了观察相应层面的结果。Android 测试基础让一个失败场景足够小以下 Kotlin 代码展示刷新失败时的状态转换。它不依赖 Android可放入独立逻辑文件真实项目可以把同样规则放进状态持有者数据读取仍通过 Repository。dataclassFeedState(valids:ListLongemptyList(),valloading:Booleanfalse,valerror:String?null)funrefreshFailed(before:FeedState,message:String):FeedStatebefore.copy(loadingfalse,errormessage)配套 JUnit 4 测试需要org.junit.Test与org.junit.Assert.assertEquals/assertFalse。下面是测试核心省略类包名代码未在本次写稿中编译。TestfunfailureKeepsExistingArticles(){valbeforeFeedState(idslistOf(11,12),loadingtrue)valafterrefreshFailed(before,网络暂不可用)assertEquals(listOf(11L,12L),after.ids)assertFalse(after.loading)assertEquals(网络暂不可用,after.error)}这个测试适合先理解需求与断言但它只覆盖状态转换。若实际请求的 catch 分支根本没有调用正确转换单独的函数测试仍会通过。因此第二步必须用 Fake 驱动完整的刷新入口让 Fake 抛出预期异常再断言公开状态。这种分层验证能区分“规则写对了”和“流程确实使用了规则”。Fake 可以返回固定文章、等待受控时间或主动失败。它实现真实依赖的接口但行为由测试控制。不要把服务端当天恰好返回的文章 ID 写死进单元测试否则文章更新就会导致无关失败。异步测试要控制的是时间不是等待得够久协程测试使用kotlinx-coroutines-test。runTest提供测试作用域通过测试 Dispatcher 和共享 scheduler可以推进使用这一调度器的挂起等待。真实 IO 线程上的阻塞并不会因此自动变成虚拟时间。协程测试搜索测试的关键顺序是先输入 A让它越过防抖并真正开始请求再输入 B推进所有相关任务最后检查结果归属。若两次输入都发生在防抖结束前A 从未请求这只能证明防抖不能证明在途请求的竞态处理。对使用viewModelScope的测试应在创建 ViewModel 前替换 Main Dispatcher并在结束后恢复。多个测试 Dispatcher 要共享同一 scheduler。长寿命观察任务应放在测试可清理的作用域内避免它们使测试一直等待。StateFlow 表示当前状态快速更新可能合并检查最终结果可以读取value不要默认收集器能看到每次中间赋值。如果通过stateIn(WhileSubscribed)产生状态先安排订阅者才能启动上游。Flow 测试指南UI 测试只保留一条有价值的跨层路径为列表提供固定的两条数据点击其中一条断言详情显示同一个 ID 对应的标题再返回检查原列表。选择语义稳定的节点避免把布局坐标当作长期定位依据。若文字本身就是产品需求的一部分可以按文字匹配若同名条目很多应补充分辨身份的语义。UI 测试负责交互结果数据库测试负责持久化两者不必在一个超长用例中包办全部任务。Compose 测试故障实验让测试证明自己能发现错误先在练习副本中把失败转换改成返回空列表预期第一个测试失败。接着保留正确转换但让刷新入口在异常时错误地清空列表预期完整流程测试失败。这样可以看到两种测试分别保护哪一层。搜索实验则准备同时缺少取消和身份检查的故障版本。若仅去掉一道保护、另一道仍有效测试通过并不反常。要单独验证请求身份需要构造不合作取消或晚到回调的受控路径不能靠给 Fake 加普通 delay 就声称覆盖所有情况。三道原创面试自测Fake 和 Mock 的区别是什么Fake 通常以简化行为替代真实依赖方便控制数据与时间Mock 更常用于设置和验证交互。追问“哪一个更好”应回到测试意图关心用户结果时不要只检查内部调用次数。测试都通过是否可以不接真实接口不能。Fake 可以证明客户端如何应对约定输入但接口路径、字段、权限和真实网络配置还要联调。追问“如何保持稳定”把可重复行为测试与少量明确的接口集成检查分开组织。覆盖率高为什么仍可能漏 bug执行某行不等于检查正确结果也可能缺少失败时序。追问“今天增加什么最值”优先补已有缓存刷新失败、搜索乱序这类能造成错误数据的行为。当天验收交付四类关键逻辑场景与一条列表到详情的 UI 流程记录它们各自保护什么。至少人为破坏一条规则并观察失败再恢复实现。能解释为什么测试失败比只截图一个绿色结果更有价值。
阅读完成 · 觉得有帮助?
咨询建站