mvn integration-test无法执行Cucumber集成测试问题排查
现有项目同时包含单元测试与基于Selenium实现的集成测试,在IntelliJ中直接运行Cucumber集成测试可正常执行,对应执行效果如下截图所示:
但执行mvn integration-test命令时,maven-failsafe-plugin无法扫描匹配到任何集成测试用例,插件输出如下截图所示:
- 项目POM配置如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.weblogism.cucumberjvm</groupId> <artifactId>java-example</artifactId> <version>1.3.0-SNAPSHOT</version> <packaging>war</packaging> <name>Cucumber-jvm Java Example</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <cucumber.plugin>pretty</cucumber.plugin> <cucumber.filter.tags>@wip</cucumber.filter.tags> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>de.flapdoodle.embed</groupId> <artifactId>de.flapdoodle.embed.mongo</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-picocontainer</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-junit</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.1.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.picocontainer</groupId> <artifactId>picocontainer</artifactId> <version>2.15</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>cuke-jvm-example</finalName> <plugins> <plugin> <artifactId>maven-enforcer-plugin</artifactId> <version>3.0.0-M3</version> <executions> <execution> <id>enforce-java</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireJavaVersion> <version>1.8.0</version> </requireJavaVersion> </rules> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>18</source> <target>18</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>versions-maven-plugin</artifactId> <version>2.7</version> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-test-source</goal> </goals> <configuration> <sources> <source>src/it/java</source> </sources> </configuration> </execution> <execution> <id>add-resource</id> <phase>generate-sources</phase> <goals> <goal>add-test-resource</goal> </goals> <configuration> <resources> <resource> <directory>src/it/resources</directory> </resource> </resources> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M4</version> </plugin> <plugin> <artifactId>maven-failsafe-plugin</artifactId> <version>3.0.0-M4</version> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> <configuration> <failIfNoTests>true</failIfNoTests> <systemPropertyVariables> <cucumber.plugin>${cucumber.plugin}</cucumber.plugin> <cucumber.filter.tags>${cucumber.filter.tags}</cucumber.filter.tags> </systemPropertyVariables> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <id>pre-integration-test</id> <goals> <goal>start</goal> </goals> </execution> <execution> <id>post-integration-test</id> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
- 项目目录结构如下截图所示
mvn integration-test命令执行输出有对应日志留存- 已配置spring-boot-maven-plugin,实现集成测试阶段前后自动启停服务
- 已配置build-helper-maven-plugin,将存放集成测试代码的
src/it目录添加为测试源目录
maven-failsafe-plugin扫描不到Cucumber测试用例是核心配置不匹配导致的,按以下步骤修复即可:
根因1:测试类命名不符合failsafe默认扫描规则
maven-failsafe-plugin默认仅扫描符合以下命名规则的测试类:
- 类名以
IT开头 - 类名以
IT结尾 - 类名以
ITCase结尾
绝大多数Cucumber测试启动类会被命名为*Test.java,这是maven-surefire-plugin(单元测试插件)的匹配规则,failsafe默认不会扫描这类文件。
修复方式
将Cucumber启动类重命名为符合规则的名称,比如CucumberIT.java,确保类上添加了正确的Cucumber JUnit4运行注解,示例代码如下:
package com.weblogism.cucumberjvm; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; import org.junit.runner.RunWith; @RunWith(Cucumber.class) @CucumberOptions( features = "classpath:features", glue = "com.weblogism.cucumberjvm.steps" ) public class CucumberIT { }
如果不想修改类名,也可以在maven-failsafe-plugin的<configuration>节点下显式配置扫描规则:
<includes> <include>**/*Cucumber*.java</include> <include>**/IT*.java</include> <include>**/*IT.java</include> <include>**/*ITCase.java</include> </includes>
根因2:3.x版本failsafe缺少JUnit4运行引擎
使用的maven-failsafe-plugin 3.0.0-M4版本默认基于JUnit Platform执行测试,而项目引入的cucumber-junit 5.6.0是基于JUnit4的组件,缺少对应引擎时插件无法识别JUnit4格式的测试类。
修复方式
在test作用域下添加JUnit Vintage引擎依赖,兼容JUnit4测试:
<dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> </dependency>
根因3:标签过滤配置可能导致无匹配用例
POM中全局配置了cucumber.filter.tags=@wip,如果所有feature场景都没有添加@wip标签,就算插件扫描到测试类,也会因为没有匹配的场景报无测试用例错误。
修复方式
要么给需要执行的集成测试场景加上@wip标签,要么调整过滤标签配置为实际需要执行的标签值。
额外配置冲突修复
POM中存在Java版本配置冲突:maven-enforcer-plugin要求Java版本为1.8.0,但maven-compiler-plugin配置的编译版本是18,这个冲突会导致部分环境下构建失败,统一两个配置的Java版本即可。
内容的提问来源于stack exchange,提问作者Joan

