用途:编写不闪烁(non-flaky)的 Compose 动画测试。默认 mainClock.autoAdvance = true 时,不确定性动画会立即抛出 CancellationException("Infinite animations are disabled on tests"),有限动画则一次性跑完、无法观察中间帧。该技能给出固定五步配方:在 setContent 之前先关闭自动推进,再手动推进帧。
主要能力与用法: 步骤:rule.mainClock.autoAdvance = false(必须在 setContent 之前);rule.setContent { ... };rule.mainClock.advanceTimeByFrame() 作为启动帧;rule.mainClock.advanceTimeBy(durationMillis = 300);最后断言。顺序很重要:切换帧只负责调度,下一帧才把 playTime 初始化为 0,缺少启动帧会导致动画差一帧。
中间帧断言可复用 onAnimationFrame 辅助函数,要求时长是 FrameDuration(16L,const val)的整数倍;其内部先 waitForIdle() 再逐帧推进。
不确定性进度条示例:autoAdvance = false 后 setMaterialContent { LinearProgressIndicator(modifier = Modifier.testTag(tag)) },advanceTimeByFrame(),再断言 ProgressBarRangeInfo.Indeterminate。
暂停时钟期间修改状态应使用 rule.runOnUiThread { ... },不要用 runOnIdle,因为后者先调用 waitForIdle,可能被 IdlingResource 卡住。等待 Compose 状态条件优先用 mainClock.advanceTimeUntil { ... },其超时是测试时钟;rule.waitUntil 是墙钟,混用会不稳定。
限制与规则:不得用 Thread.sleep 等待动画;测试之间不要遗留 autoAdvance = false;优先使用 v2 入口(androidx.compose.ui.test.junit4.v2.createComposeRule)。若只关心最终状态、时钟语义不清、条件非 Compose 状态,或截图比较等待 RenderThread 像素,则不适合用此技能。依赖 androidx.compose.ui:ui-test 与 ui-test-junit4(或无 JUnit 的 runComposeUiTest)。