Maven项目中Cucumber+Selenium报错:无可运行方法
这个问题我之前排查过,核心原因是你在Cucumber的步骤定义类上误用了JUnit的参数化运行器,导致JUnit和Cucumber的执行逻辑冲突,才抛出"没有可运行方法"的错误。
问题拆解
你的CucumberStepDefs类上标注了@RunWith(value = Parameterized.class)——这是JUnit用来做参数化测试的运行器,但Cucumber有自己的执行逻辑:它靠@Given/@When/@Then注解识别步骤,而JUnit的BlockJUnit4ClassRunner会强制扫描类中的@Test注解方法,你的步骤定义里没有符合要求的@Test方法,所以直接报错了。
另外,用JUnit Parameterized来给Cucumber步骤传参本身就是错误的思路,Cucumber有专门的参数化方案,完全不需要依赖JUnit的运行器。
分步解决
1. 清理步骤定义类的JUnit注解
把CucumberStepDefs上的@RunWith(Parameterized.class)、@Parameterized.Parameter、@Parameterized.Parameters全部删掉,这些是JUnit的东西,和Cucumber不兼容。修改后的类结构如下:
import cl.chipacorp.test.SolutAutomatedWebTest; import cl.chipacorp.util.report.Report; import cucumber.annotation.en.Given; import cucumber.annotation.en.Then; import cucumber.annotation.en.When; import org.openqa.selenium.By; import org.openqa.selenium.ie.InternetExplorerDriver; import java.util.concurrent.TimeUnit; // 移除所有JUnit参数化相关注解 public class CucumberStepDefs extends CoopeuchAutomatedWebTest { @Given("^Ingresar a la URL de Branch en ambiente QA$") public void Login() throws Exception { driver = new InternetExplorerDriver(); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); baseUrl = "http://brs1coreqa-01.coopeuch1.cl/"; driver.get(baseUrl + "IBSBranchnet_COOPEUCH_Q5A/WebTeller.htm"); driver.switchTo().defaultContent(); driver.switchTo().frame("frmbody"); } // 修改步骤为带参数的形式,让Cucumber传递用户名和密码 @When("^Se desplieguen los campos Username y Password, Ingresar usuario \"([^\"]*)\" y contraseña \"([^\"]*)\"$") public void UsuarioPass(String usuario, String pass) throws Exception { driver.findElement(By.id("TxbTELLUSERID")).clear(); driver.findElement(By.id("TxbTELLUSERID")).sendKeys(usuario); driver.findElement(By.id("TxbUSERPASSW")).clear(); driver.findElement(By.id("TxbUSERPASSW")).sendKeys(pass); screenshot.take(this, driver, "LoginR C01"); driver.findElement(By.id("BtnSubmit")).click(); } @Then("^Usuario accede a Branch con su correspondiente usuario$") public void Logout() throws Exception { driver.switchTo().defaultContent(); driver.switchTo().frame("frmwebteller"); driver.manage().window().maximize(); screenshot.take(this, driver, "LoginR C02"); driver.switchTo().defaultContent(); driver.switchTo().frame("frmbody").switchTo().frame("menu"); driver.findElement(By.cssSelector("b")).click(); screenshot.take(this, driver, "LoginR C03"); // 建议添加driver退出逻辑,避免浏览器进程残留 driver.quit(); } }
2. 用Cucumber的Scenario Outline实现参数化
更新你的Login.feature文件,使用Scenario Outline+Examples来传递多组测试数据,这是Cucumber标准的参数化方式:
Feature: 分支系统登录验证 Scenario Outline: 测试不同用户登录流程 Given Ingresar a la URL de Branch en ambiente QA When Se desplieguen los campos Username y Password, Ingresar usuario "<usuario>" y contraseña "<pass>" Then Usuario accede a Branch con su correspondiente usuario Examples: | usuario | pass | | testUser1 | testPwd1 | | testUser2 | testPwd2 | # 可以继续添加更多测试用例
3. 确认Cucumber运行器类无误
你的CucumberRunnerTest类是正确的,不需要修改,只要确保glue属性指向步骤定义类所在的包就行:
import cucumber.api.CucumberOptions; import cucumber.api.junit.Cucumber; import org.junit.runner.RunWith; @RunWith(Cucumber.class) @CucumberOptions( features={"src/features/Login.feature"}, format = {"pretty", "html:target/cucumber"}, glue = {"cucumber.CucumberStepDefs"} ) public class CucumberRunnerTest { }
特殊场景处理
如果你的测试数据必须从外部文件/数据库读取(而不是写在Feature里),可以通过Cucumber的DataTable或者自定义参数解析器来实现,或者在步骤定义类里直接读取数据源,绝对不要用JUnit的Parameterized运行器,它和Cucumber的执行流程完全不兼容。
内容的提问来源于stack exchange,提问作者nosequeweaponer

