Compose Multiplatform 编译器集成测试指南:用 checkComposeCases 验证 Compose 编译器行为
发布时间:2026/9/13 21:46:38 作者:尧图编辑部 阅读量:1,286

Compose Multiplatform 编译器集成测试指南用 checkComposeCases 验证 Compose 编译器行为【免费下载链接】compose-multiplatformCompose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.项目地址: https://gitcode.com/GitHub_Trending/co/compose-multiplatformCompose 编译器Compose Compiler Gradle 插件负责将Composable函数与 lambda 变换为带有重组能力recomposition的运行时调用其正确性直接影响 UI 行为。本指南基于html/compose-compiler-integration模块系统讲解如何使用checkComposeCases测试任务验证 Compose 编译器在匿名对象、构造函数、继承、lambda 调用与稳定性等典型场景下的表现读完即可掌握测试命令、用例组织方式passing/failing与跨模块测试设计思路。模块定位一个面向 Compose 编译器的集成测试套件html/compose-compiler-integration是仓库中 HTML 目标平台Compose for Web下的编译器集成验证模块。它不直接提供业务功能而是通过大量可运行的测试用例逐项验证 Compose 编译器插件在处理各类 Kotlin 语法构造时能否正确生成代码并同时校验运行时的 DOM 渲染结果。从 目录结构 看模块由四部分组成src/jsTest/核心测试代码全部在 JS 目标平台运行覆盖编译器行为的五个测试类src/jsMain/跨模块测试依赖——被测试的类定义如存放Composablelambda 的 data class、interface被刻意放在jsMain以验证跨模块编译与运行时行为lib/独立库模块提供ComposableCollection、ComposableContent等供测试使用的接口与抽象类main-template/一个带 Gradle Wrapper 的模板项目用于按指定 Compose 版本复现编译器问题testcases/passing/与testcases/failing/按目录划分的源码用例集合供过滤任务筛选。三个核心命令跑通、指定版本、过滤用例README 提供了三个命令行用法均需在仓库根目录执行1. 运行全部测试用例./gradlew :compose-compiler-integration:checkComposeCases该任务会编译jsTest中的全部测试类并执行任何编译器错误或断言失败都会导致构建失败。2. 使用指定 Compose 版本./gradlew :compose-compiler-integration:checkComposeCases -Pcompose.version1.2.0-beta03通过-Pcompose.version属性覆盖默认的 Compose 插件版本。从 main-template/settings.gradle.kts 的resolutionStrategy逻辑可见其版本解析机制若通过-Pcompose.version指定版本则优先使用该版本否则回退到0.0.0-SNAPSHOT用于配合本地发布的快照构建同时org.jetbrains.kotlin系列插件统一使用kotlin.version属性指定的 Kotlin 版本。因此该命令常用于验证新版本 Compose 编译器是否修复了已知问题或是否引入了回归。3. 仅运行文件路径中包含指定名称的用例./gradlew :compose-compiler-integration:checkComposeCases -PFILTER_CASESCaseName-PFILTER_CASES依据文件路径进行过滤filtered cases check for contained in file path。例如过滤值为Stability时可只运行StabilityTests.kt便于在迭代单个编译器问题时缩短反馈回路。用例组织passing 与 failing 双目录testcases/目录按预期结果分为两档这是该套件区别于普通单元测试的设计亮点testcases/passing/包含 9 个应当编译通过并正确运行的用例如ComposableWithTypeParams.kt、ComposableWithParamsWithDefaultValues.kt、ComposableWithNullableTypeParameter.kt、ComposableWithTypedDefaultValues.kt、PassingComposableToConstructor.kt、WithComposableBlockUsingTypeParameterAndDefaultValue.kt等覆盖泛型参数、默认值、可空类型参数、构造器传参等编译器边界场景testcases/failing/包含已知问题的复现用例如 MutableStateDestructuringDeclarartion.kt对应 YouTrack 问题 CMP-5176var (foo, setFoo) mutableStateOf(0)的解构声明在旧版本编译器下foo不会随状态更新测试通过require(foo 123)显式断言当前行为是错误的——一旦问题修复该用例会转为失败起到回归哨兵作用。五类核心测试场景与源码佐证匿名对象与局部类中的 ComposableCMP-2549AnonymousObjectsInComposable.kt 验证三处编译器容易出错的场景匿名对象object : HasComposable2中重写带Composable标注的方法Composable 函数内部声明的局部类local class中实现接口的Composable方法构造函数中接收Composable () - Unit参数并存入属性、再由其他 lambda 间接调用。这三类场景曾在旧编译器下分别报出content.Abc$composable_z540rc_k$ is not a functionCMP-2549与Could not find local implementation for Abc$composableDecoyTransformBase 找不到本地实现等错误。测试用renderComposableInBody渲染并断言最终 DOM 为divAbc/div、divAbc2/div、divAbc223-111/div从编译期与运行期双重验证修复结果。Composable lambda 的多种调用形态ComposableLambdaCalls.kt 覆盖Composablelambda 的七种调用方式场景断言结果函数引用作为参数传入 ComposabledivSomeText/div匿名 lambda 传入 ComposabledivText1/div无参 Composable lambda 直接调用divTextA/div可空 Composable lambda 用?.invoke()div/div且参数函数不会被求值带参数 Composable lambdainvoke(10)divText10/div以函数引用作为参数的 Composable lambdadivText-SomeText/div跨模块的全局 Composable lambda定义于 jsMaindivSuperText/div其中可空 lambda 的用例还断言了短路语义当l为 null 时l?.invoke(someInt())不会调用someInt()验证编译器对可空 Composable 引用的处理不会引入多余副作用。构造函数中存放 Composable 的十一种形态CMP-6299、CMP-5305ComposablesInConstructorTests.kt 与其对应的 CrossmoduleTestsDependencies.kt 共同构成一个覆盖矩阵被测试的 data class / class 定义在jsMain跨模块测试位于jsTest。覆盖形态包括val/var/ 泛型val类型的 Composable 属性data class 与普通 class实现带 Composable 属性接口HasComposable、HasComposableTypedTComposable 存入普通var、lateinit var、可空var带接收者的 ComposableComposable ClassName.() - Unit与普通参数并存private val持有 Composable 并由内部函数调用二次构造函数secondary constructor在委托调用中注入 Composable 内容。所有用例统一使用SideEffect { document.body!!.innerText ... }在组合composition提交阶段写入结果文本再经renderComposableInBody渲染后断言验证的是组合真正发生而非仅编译通过。接口实现、委托与抽象类继承CMP-2291、CMP-2660InheritanceTests.kt 配合 lib 模块的 Interfaces.kt 验证继承体系下的编译器行为ComposableCollection接口暴露ListComposable () - Unit与add方法测试向其添加三个块后逐个调用断言root.innerHTML为三个div拼接ComposableContent接口声明Composable fun ComposableContent()实现类渲染ComposableContent接口委托ComposableContentDelegation通过by impl委托调用委托后的方法仍能正确渲染抽象类两种继承形态AbstrComposableContentExtendImpl在super.ComposableContent()之后追加内容断言两段输出AbstrComposableContentNoExtendImpl不覆写断言仅抽象类默认输出。该组用例证明编译器对 Composable 成员在接口默认实现、类委托与抽象类覆写链条中均能生成正确的 decoy替身与调用关系。稳定性稳定类型能否跳过不必要的重组CMP-2539、CMP-2535StabilityTests.kt 是五类中唯一引入协程与重组计数器的测试验证编译器的稳定性stability推断是否正确对 sealed interfaceStableSealedInterface、data classStableDataClass、普通 classStableClass与泛型 classStableTypedClassT建立mutableStateOf状态通过scope!!.invalidate()主动触发重组断言参数未变时 Composable 体内的counter不再增长——即编译器将上述类型推断为稳定类型后跳过无意义重组当状态值真正改变如state.value StableSealedInterface.B时counter才 1验证变更可被正确感知。test_remembers_correct_attrs对应 CMP-2535则验证remember { mutableStateListOfString() }在多次点击按钮追加元素后lastPText().innerText始终为最近一次点击所添加的文本最终断言九次点击后 DOM 序列为foo,foo,foo,abc,abc,abc,bar,bar,bar防止编译器错误地复用/混淆 remember 保存的属性。跨模块编译与模板项目如何复现并隔离编译器问题该套件特意将被测类定义与测试代码分置于不同编译单元这一点在 ComposablesInConstructorTests.kt 的 KDoc 中有明确说明目的是测试跨模块编译cross-module compilation加运行时行为——Compose 编译器在不同模块间通过 decoy 机制衔接单模块测试无法暴露此类问题。同时main-template 是一个可独立运行的模板工程其settings.gradle.kts通过resolutionStrategy动态切换 Compose/Kotlin 插件版本lib/提供最小库模块Expect.kt 使用expect fun callComposable(content: Composable () - Unit)的 expect/actual 模式声明跨平台入口Main.kt为空文件仅作工程骨架。当某个问题只在特定 Compose 版本出现时可基于该模板配合-Pcompose.version快速复现而不必运行整个测试套件。在仓库整体中的位置该模块是html/目录Compose for Web / HTML 实现下的一个独立 Gradle 子项目与html/core、html/svg等实现模块并列仓库根目录的settings.gradle.kts将其纳入构建。需要注意的是所有测试都运行在 JS 目标平台使用kotlin.test的Test/assertEquals与kotlinx.browser.document直接断言渲染出的 DOM HTML 字符串是典型的浏览器端集成测试形态checkComposeCases属自定义 Gradle 任务名结合-PFILTER_CASES过滤与testcases/双目录设计可同时服务于新用例回归保护与已知问题追踪两个目标。小结通过html/compose-compiler-integration模块可以看到Compose Multiplatform 对编译器正确性的保障依赖一套命令 用例目录 跨模块测试的组合checkComposeCases提供一键验证入口-Pcompose.version支持针对特定版本复现-PFILTER_CASES支持定向调试而 passing/failing 双目录与按问题号CMP-xxxx组织的测试注释则为后续维护者提供了清晰的回归追踪线索。对于在自己的 Compose 工程中遇到某语法在编译器升级后行为变化的读者参照该模块的测试形态建立同样的集成用例是成本最低的防线。【免费下载链接】compose-multiplatformCompose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.项目地址: https://gitcode.com/GitHub_Trending/co/compose-multiplatform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考