Cucumber中如何根据Maven命令执行指定标签的@Before钩子方法
首先得帮你揪出问题根源:你的Scenario同时标记了@Chrome和@Firefox标签!当你运行mvn test -Dcucumber.options="--tags @Chrome"时,这个带双标签的场景会被选中执行,而Cucumber的Hook规则是只要场景包含Hook的目标标签,就会触发对应的@Before方法——所以两个setup都跑起来了,这完全是符合规则的“意外”。
下面给你几个实用的解决方案,按推荐程度排序:
方案1:拆分场景的浏览器标签(最推荐)
不要在同一个Scenario上同时打多个浏览器标签,要么拆分独立场景,要么用场景大纲参数化浏览器:
拆分独立场景示例
Feature: Storybook @Test @Widgets @Smoke @Chrome Scenario: Storybook example on Chrome Given The user clicks on "storybook" index on the homepage And Storybook HomePage should be displayed @Test @Widgets @Smoke @Firefox Scenario: Storybook example on Firefox Given The user clicks on "storybook" index on the homepage And Storybook HomePage should be displayed
场景大纲参数化示例
Feature: Storybook @Test @Widgets @Smoke Scenario Outline: Storybook example for <browser> Given The user clicks on "storybook" index on the homepage And Storybook HomePage should be displayed Examples: | browser | tags | | Chrome | @Chrome | | Firefox | @Firefox |
这样运行mvn test -Dcucumber.options="--tags @Chrome"时,只有带@Chrome的场景会执行,对应的@Before("@Chrome")才会触发,另一个Hook自然不会跑。
方案2:在Hook中通过Scenario对象过滤标签
如果必须保留同一个场景的多浏览器标签,可以在Hook方法里注入Scenario对象,手动判断当前场景的标签来执行对应逻辑:
import io.cucumber.java.Scenario; public class Hooks { @Before public void setUp(Scenario scenario) { if (scenario.getSourceTagNames().contains("@Chrome")) { setUpChrome(); } else if (scenario.getSourceTagNames().contains("@Firefox")) { setUpFirefox(); } } private void setUpChrome() { // Chrome专属初始化逻辑 } private void setUpFirefox() { // Firefox专属初始化逻辑 } @After public void tearDown(){} }
不管场景带多少标签,只会根据当前实际运行的场景标签(也就是你Maven命令筛选后的结果)执行对应的setup。
方案3:用标签表达式精确筛选场景
如果不想改代码和Feature文件,可以用更严格的标签表达式,只运行带@Chrome但不带@Firefox的场景:
mvn test -Dcucumber.options="--tags '@Chrome and not @Firefox'"
不过这个方案的局限性很大——如果你的场景都同时带两个标签,会直接没有可执行的用例,所以只适合临时测试用。
补充:关于Runner类的tags选项无效问题
你提到在@CucumberOptions里加tags没效果,是因为当你通过Maven传递-Dcucumber.options参数时,它会覆盖Runner类里的所有Cucumber配置。如果想通过Runner类指定标签,直接在配置里设置,然后不要加Maven参数:
@RunWith(Cucumber.class) @CucumberOptions( plugin = {"pretty", "json:target/cucumber-reports/Cucumber.json", "junit:target/cucumber-reports/Cucumber.xml", "html:target/cucumber-reports"}, features = {"src/test/features/"}, glue = {"steps"}, tags = "@Chrome" // 直接在这里指定标签 ) public class RunCukesTest { }
之后直接运行mvn test就行,不需要额外参数。
内容的提问来源于stack exchange,提问作者sayhan

