Surefire 3.6.0 构建成功却零测试,检查 provider 的 include 匹配
Surefire 3.6.0 的 JUnit Platform provider 可能过滤掉扫描器已找到的测试。已确认项目可退回 3.5.6,并核对实际数量和回退后的零测试失败保护。
升级 Surefire 项目中的 Maven 测试插件到 3.6.0 后,BUILD SUCCESS 旁边却变成 Tests run: 0,先核对测试数,再检查 include 模式在哪一层生效。尤其是 Failsafe 的集成测试,扫描器找到 class,不等于 fork 内的 JUnit Platform provider 最后仍会执行它。
一个明确的回归组合是 Jupiter 测试 com.example.it.SampleIT,配合以下 include:
<include>com/example/it/**/*IT.java</include>
同一项目在 3.5.6 运行一个测试,3.6.0 运行零个,构建仍成功。**/*IT.java 与 com/example/it/*IT.java 在该对照中正常;带目录层级的中间 **、部分 %regex[...] 类文件路径模式则失效。因此不要仅凭一个简化通配符能运行,就断言配置或测试代码没有问题。
3.6.0 新的 provider 过滤会将扫描器使用的文件路径模式交给类名过滤。前者处理类似 com/example/it/SampleIT.class 的路径,后者面对 com.example.it.SampleIT。中间目录匹配和 .class 路径正则的语义不同,类在 fork 内再次过滤时被丢弃。把 JUnit 升降一次并不能自动修正这层转换。
临时方案是恢复这个测试工程已确认能运行的 3.5.6 插件基线。若 Surefire 与 Failsafe 共用版本属性,应一起核对,不要只改一个插件,然后误以为 verify 阶段也已经回退:
<properties>
<test.plugins.version>3.5.6</test.plugins.version>
</properties>
将现有的 maven-surefire-plugin、maven-failsafe-plugin 的 <version> 指向该属性,保留原来的 executions、include/exclude 与其他配置。项目由父 POM 管理插件时,在实际生效的 pluginManagement 或约定入口修改;不要凭这段属性自己新增一套覆盖原有测试生命周期的配置。
回退到已确认的 3.5.6 后,再在相关插件中启用空测试失败保护:
<configuration>
<failIfNoTests>true</failIfNoTests>
<!-- 保留原有 includes、excludes 等配置 -->
</configuration>
它不修正匹配器,而且不能依赖受影响的 3.6.0 保证零测试时失败:该版本也有设置此项后仍然绿色构建的具体表现。回退后应故意使用不匹配模式做一次负向验收,确认保护真的生效。若项目本来允许某些模块没有测试,需要在应该有测试的模块或 CI 阶段设置,不应强加给所有模块。
重跑原来的 mvn verify,检查 Failsafe/Surefire 报告中的实际测试类和数量。最小工程至少要出现 SampleIT 的一个用例;业务项目按原有验收清单核对,不能只看 Maven 退出码。使用 -X 时,若日志已列出 Tests to run 却最终为零,可将排查点收窄到 fork/provider 过滤,而不是反复挪动测试目录。
这项临时回退没有声称后续 3.6.1 已正式修复;正式含修补版本仍需确认。若因其他需求必须保留 3.6.0,不要直接删除全部过滤器来换取非零数量,否则可能执行本应排除的测试。先在可控最小工程核对模式,再决定局部调整是否符合原来的选择范围。


