Cucumber BDD参数化报UndefinedStepException异常如何解决
Cucumber BDD参数化测试步骤未定义报错修复
问题现象
- 测试执行时Chrome浏览器正常启动,目标登录页可正常加载
- 运行到账号密码输入步骤时中断,抛出
io.cucumber.junit.UndefinedStepException,提示User enters Sai and 12345等共2个步骤未定义
关联代码
TestRunner 测试运行器
package StepDefinitions; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; import org.junit.runner.RunWith; @RunWith(Cucumber.class) @CucumberOptions( features="src/test/resources/Features", glue={"StepDefinitions"}, monochrome=true ) public class TestRunner {}
LoginDemoSteps 步骤定义类
package StepDefinitions; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import io.cucumber.java.en.*; public class LoginDemoSteps { WebDriver driver = null; @Given("browser is open") public void browser_is_open() { System.setProperty("webdriver.chrome.driver",System.getProperty("user.dir")+"\\src\\test\\resources\\drivers\\chromedriver.exe"); driver=new ChromeDriver(); driver.manage().window().maximize(); } @And("user is on login page") public void user_is_on_login_page() { driver.get("https://example.testproject.io/web/"); } @When("^User enters (.*) and (.*) $") public void User_enters_username_and_password(String username, String password) throws InterruptedException { driver.findElement(By.id("name")).sendKeys(username); driver.findElement(By.id("password")).sendKeys(password); Thread.sleep(3000); } }
登录场景feature文件
Feature: Test login functionality Scenario Outline: Check login is successful with valid credentials Given browser is open And user is on login page When User enters <username> and <password> Examples: | username | password | | Sai | 12345 | | Ele | 12345 |
根因分析
Cucumber步骤匹配要求步骤定义的表达式和feature文件中的步骤文本完全精确匹配,多/少空格、参数类型不匹配都会导致匹配失败,本次报错的两个触发点:
- 步骤注解的正则表达式末尾存在冗余空格:
@When里写的正则是^User enters (.*) and (.*) $,结尾定位符$前多了一个空格,要求匹配的步骤文本末尾必须带空格,但feature文件中的对应步骤末尾无空格,直接导致匹配失效 - 正则使用
(.*)通配符未做类型约束,对于数字格式的密码12345,Cucumber默认优先匹配精度更高的整数类型规则,因此报错给出的待实现片段将第二个参数识别为{int}类型,和现有方法的String类型参数不匹配
修复方法
修改步骤定义的@When注解即可,两种方案均有效:
方案1:修正原有正则
删除正则末尾的冗余空格,增加非贪婪匹配限定避免参数越界,修改后代码:
@When("^User enters (.*?) and (.*?)$") public void user_enters_username_and_password(String username, String password) throws InterruptedException { driver.findElement(By.id("name")).sendKeys(username); driver.findElement(By.id("password")).sendKeys(password); Thread.sleep(3000); }
注:方法名首字母建议改为小写,符合Java编码规范,不影响运行但可提升代码可读性
方案2:使用Cucumber表达式替代正则(推荐,维护成本更低)
不需要写正则首尾定位符,直接用官方提供的参数占位符,不需要手动处理空格问题:
@When("User enters {string} and {string}") public void user_enters_username_and_password(String username, String password) throws InterruptedException { driver.findElement(By.id("name")).sendKeys(username); driver.findElement(By.id("password")).sendKeys(password); Thread.sleep(3000); }
注:{string}占位符可兼容字符串、数字格式的账号密码,不需要单独区分参数类型,比正则写法更不容易出错
验证
修改后重新运行测试类,步骤可正常匹配,浏览器会自动填入Examples中配置的两组测试凭据,不再抛出步骤未定义异常。
内容的提问来源于stack exchange,提问作者Jackie M
相关产品推荐
相关产品推荐

