You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maven项目中Cucumber+Selenium报错:无可运行方法

解决Cucumber + Selenium中"java.lang.Exception: No runnable methods"报错

这个问题我之前排查过,核心原因是你在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:18:25