多模块项目中配置Pitest关联Cucumber测试的技术问题
问题描述
项目结构
project/ ├── module-with-java-code/ │ ├── main │ ├── test │ └── build.gradle ├── module-with-cucumber-features/ │ ├── features [test]/ │ │ ├── feature-test-folder-1/ │ │ │ ├── test-1.feature │ │ │ └── ... │ │ └── ... │ ├── test/ │ │ ├── glue/ │ │ │ └── ... │ │ ├── TestNgCucumberTest for feature-test-folder-1 │ │ └── ... │ └── build.gradle ├── ...更多模块... └── build.gradle
需求
对module-with-java-code模块执行Pitest变异测试,同时使用该模块自身的单元测试和module-with-cucumber-features模块中的Cucumber测试用例。
使用版本
- gradle: 8.11.1
- pitest-gradle-plugin:
info.solidsoft.pitest:1.15.0 - pitest-testng-plugin:
org.pitest:pitest-testng-plugin:1.0.0 - pitest-junit5-plugin:
org.pitest:pitest-junit5-plugin:1.2.1 - Cucumber依赖:
io.cucumber:cucumber-jvm-deps:1.0.6io.cucumber:cucumber-picocontainer:7.20.1io.cucumber:cucumber-java:7.20.1io.cucumber:cucumber-testng:7.20.1me.jvt.cucumber:reporting-plugin:7.11.0
遇到的问题
问题1:在module-with-cucumber-features模块配置时,报错No mutations found
配置代码:
configure(project(':module-with-cucumber-features')) { apply plugin: 'info.solidsoft.pitest' dependencies { implementation project(':module-with-java-code') } configurations { mutableCodeBase { transitive false } } dependencies { mutableCodeBase project(':module-with-java-code') } pitest { mutators = ["ALL"] mainSourceSets = [project(':module-with-java-code').sourceSets.main] testSourceSets = [sourceSets.test] targetTests = ['com.example.TestNgCucumberTest'] additionalMutableCodePaths = [configurations.mutableCodeBase.singleFile] } }
问题2:在根项目配置时,报错Could not get unknown property 'implementation' for configuration container for project ':module-with-java-code'
配置代码:
configure(project(':module-with-cucumber-features')) { apply plugin: 'info.solidsoft.pitest' apply plugin: 'java' dependencies { implementation project(':module-with-java-code') } //Additional configuration to resolve :module-with-java-code project JAR as mutable code path for PIT configurations { mutableCodeBase { transitive false } dependencies { mutableCodeBase.extendsFrom(project(':module-with-java-code').configurations.implementation) } } pitest { timestampedReports = false mainSourceSets = [project.sourceSets.main, project(':module-with-java-code').sourceSets.main] //Generates deprecation warning in Gradle 5.6+ additionalMutableCodePaths = configurations.mutableCodeBase.files // additionalMutableCodePaths = project(':module-with-java-code').jar.outputs.files.getFiles() //Workaround } }
解决方案
正确的做法是在module-with-java-code模块中配置Pitest,同时引入Cucumber模块的测试代码作为额外测试源,避免反向配置带来的路径和依赖问题。
步骤1:配置module-with-java-code的build.gradle
plugins { id 'java' id 'info.solidsoft.pitest' } dependencies { // 保留自身单元测试的依赖(如JUnit/TestNG) testImplementation ... // 引入Cucumber模块的测试代码与资源 testImplementation project(':module-with-cucumber-features') // 配置Pitest所需的测试框架插件 pitest 'org.pitest:pitest-testng-plugin:1.0.0' pitest 'org.pitest:pitest-junit5-plugin:1.2.1' } pitest { // 指定要变异的目标源码(当前模块的业务代码) mainSourceSets = [sourceSets.main] // 同时加载自身测试和Cucumber模块的测试代码 testSourceSets = [sourceSets.test, project(':module-with-cucumber-features').sourceSets.test] // 指定要运行的测试类:自身单元测试 + Cucumber的TestNG运行器 targetTests = ['com.yourpackage.*Test', 'com.example.TestNgCucumberTest'] mutators = ["ALL"] timestampedReports = false // 确保Cucumber的feature文件能被加载到测试类路径 additionalTestClasspath = project(':module-with-cucumber-features').sourceSets.test.resources.srcDirs }
步骤2:调整module-with-cucumber-features的build.gradle
确保测试资源(.feature文件)能被其他模块访问:
plugins { id 'java' } sourceSets { test { resources { srcDir 'features' // 对应项目中的features目录 } } } dependencies { implementation project(':module-with-java-code') // 保留原有的Cucumber依赖配置 testImplementation 'io.cucumber:cucumber-java:7.20.1' testImplementation 'io.cucumber:cucumber-testng:7.20.1' testImplementation 'io.cucumber:cucumber-picocontainer:7.20.1' testImplementation 'io.cucumber:cucumber-jvm-deps:1.0.6' testImplementation 'me.jvt.cucumber:reporting-plugin:7.11.0' }
步骤3:执行Pitest任务
在项目根目录运行以下命令:
./gradlew :module-with-java-code:pitest
问题原因分析
- 问题1(No mutations found):在Cucumber模块配置时,
additionalMutableCodePaths指向的是打包后的JAR文件,而Pitest需要直接访问未打包的编译类文件。通过mainSourceSets指定目标源码才是正确的方式。 - 问题2(unknown property 'implementation'):
project(':module-with-java-code').configurations.implementation写法错误,Gradle中不能直接通过配置容器访问implementation配置。直接在目标模块配置Pitest可完全避免这种复杂的跨模块依赖引用。
内容的提问来源于stack exchange,提问作者Daniël Gerritsen
相关产品推荐
相关产品推荐

