Cucumber钩子并行执行顺序失效问题排查求助
我基于Selenium框架编写了Cucumber测试用例,串行执行时全部通过,但并行执行时测试失败。核心问题是所有测试共用同一用户,测试流程为:登录DARTTS应用→修改语言并验证→登出后重新登录以验证用户语言设置的持久性,且每个测试对应不同语言。
问题具体表现:测试1执行到登出重登步骤时,测试2已在运行并修改了语言,导致测试1的语言验证失败。我尝试通过Hooks控制场景执行顺序,但未生效,不确定是否实现方式有误。
Feature文件代码
@Profile @VerifyLanguageSetPortugues Scenario Outline: Profile tests(Verify App Languages selection Espanol) Given "guest" user login to app "DARTTS" using "AppAuth" Then I verify previous language setting is active from app title "<Current AppTitle>" And I click on language "<Language>" Then I verify selected language for "<Field1>" "<Field2>" "<Field3>" And I logout and log back in And I verify previous language setting is active from app title "<Previous AppTitle>" When I click on user profile button Then I should log out of Raven app Examples: | Language | Current AppTitle | Previous AppTitle | Field1 | Field2 | Field3 | | Português | Analyze | Analisar | Clique no botão \"novo grupo de filtros\" para criar seu primeiro grupo de filtros. | Selecione um filtro para mostrar os resultados nesta tela. | Expandir explorar e tabular as estatísticas | @Profile @VerifyLanguageSetEspanol Scenario Outline: Profile tests(Verify App Languages selection Espanol) Given "guest" user login to app "DARTTS" using "AppAuth" Then I verify previous language setting is active from app title "<Current AppTitle>" And I click on language "<Language>" Then I verify selected language for "<Field1>" "<Field2>" "<Field3>" And I logout and log back in And I verify previous language setting is active from app title "<Previous AppTitle>" When I click on user profile button Then I should log out of Raven app Examples: | Language | Current AppTitle | Previous AppTitle | Field1 | Field2 | Field3 | | Español | Analyze | Analizar | Haga clic en el botón \"novo grupo de filtros\" para criar su primer grupo de filtros. | Seleccione un grupo de filtros para mostrar los resultados en esta pantalla. | Ampliar la exploración y las estadísticas de las columnas |
Hooks类代码
public class Hooks { @Before(order = 1, value = "@VerifyLanguageSetPortugues") public void portuguesLangBeforeScenario() { System.out.println("This should run first"); } @After(order = 4, value = "@VerifyLanguageSetPortugues") public void portuguesLangAfterScenario() { System.out.println("This should end first"); } @Before(order = 2, value = "@VerifyLanguageSetEspanol") public void espanolLangBeforeScenario() { UIPgAct.driverWait(55000); System.out.println("This should run second"); } @After(order = 3, value = "@VerifyLanguageSetEspanol") public void espanolLangAfterScenario() { System.out.println("This should end second"); System.out.println("Espanol language is set to true"); }
执行输出
11:01:59.545 [TestNG-PoolService-1] INFO gov.dhs.ice.raven.resources.base - Detected Dartts scenario tag. 11:02:05.474 [TestNG-PoolService-0] INFO gov.dhs.ice.raven.resources.base - WebDriver setup is complete This should run first 11:02:05.548 [TestNG-PoolService-1] INFO gov.dhs.ice.raven.resources.base - WebDriver setup is complete This should run second
问题根源
Cucumber的Hooks order 参数仅能控制同一个场景内的Hooks执行顺序,无法跨线程控制不同场景的并行执行顺序。从执行输出的TestNG-PoolService-0/1可以看出,两个场景被分配到了不同线程,Hooks的order参数和等待逻辑完全无法让第二个场景等待第一个场景完成。
解决方案
方案1:为每个测试分配独立用户
这是最彻底的解决方式,符合并行测试无状态、互相隔离的核心原则。给每个语言测试分配专属测试用户,修改语言的操作只会影响当前用户,不会干扰其他测试的验证步骤。
方案2:强制目标场景串行执行
如果暂时无法新增测试用户,可以通过测试框架配置,让@VerifyLanguageSetPortugues和@VerifyLanguageSetEspanol标签的场景强制串行:
- 若使用TestNG,在
testng.xml中配置分组,将目标测试分到同一组并设置线程数为1:
<test name="LanguageTests" parallel="none"> <groups> <run> <include name="VerifyLanguageSetPortugues"/> <include name="VerifyLanguageSetEspanol"/> </run> </groups> </test>
- 若使用Cucumber原生并行配置(如
cucumber.properties),给目标场景单独设置并行池,线程数设为1:
cucumber.execution.parallel.enabled=true cucumber.execution.parallel.config.strategy=fixed cucumber.execution.parallel.config.fixed.parallelism=2 # 为语言测试组单独配置串行 cucumber.execution.groups.group=language-tests cucumber.execution.groups.group.language-tests.tags="@VerifyLanguageSetPortugues or @VerifyLanguageSetEspanol" cucumber.execution.groups.group.language-tests.parallel.config.fixed.parallelism=1
方案3:测试前重置用户语言到初始状态
在每个场景的@Before Hook中,先登录用户并将语言重置为默认英文(即Current AppTitle对应的Analyze),再执行后续测试步骤,确保每个测试开始时都是初始状态:
@Before(order = 1, value = "@Profile") public void resetLanguageBeforeScenario() { // 执行登录步骤 loginToDARTTS("guest", "AppAuth"); // 检查当前语言,非默认则切换回英文 if (!getCurrentAppTitle().equals("Analyze")) { switchToLanguage("English"); } // 登出,让测试用例自行重新登录 logoutFromDARTTS(); }
当前Hooks的问题说明
你给@VerifyLanguageSetEspanol的@Before添加的55秒等待,只是让当前线程暂停,其他线程(如葡萄牙语测试的线程)仍会继续执行,完全起不到顺序控制的作用。且Hooks的order参数仅对同一个场景内的多个Hooks有效,跨场景不生效。
内容的提问来源于stack exchange,提问作者VinnyTech

