Cucumber Selenium中如何在不同Feature中复用相同步骤?
Cucumber Selenium中如何在不同Feature中复用相同步骤?
这个问题我之前也碰到过!核心问题就是公共步骤的Driver上下文没对应上——你把i am logged in放在A类里,跑B.feature的时候,B类的Driver还没初始化,而A类的@Before也不会因为执行B的场景而触发,导致步骤里的Driver实例未初始化报错。下面给你两个实用的解决方案:
方案一:用单例类统一管理Driver
把Driver的创建、销毁逻辑抽成一个全局管理类,所有步骤都通过这个类获取Driver,这样公共步骤就不用绑定到某个测试类了。
- 先创建Driver管理单例:
object DriverManager { lateinit var webDriver: WebDriver fun initDriver() { // 这里替换成你的Driver初始化逻辑,比如ChromeDriver webDriver = ChromeDriver() } fun quitDriver() { if (::webDriver.isInitialized) { webDriver.quit() } } }
- 单独写公共步骤类,存放所有复用的步骤:
class CommonSteps { @Given("i am logged in") fun logInChecking() { DriverManager.webDriver.get("你的登录页面URL") // 这里补充登录的具体逻辑,比如输入账号密码、点击登录按钮等 } }
- 修改你的测试类,让它们通过DriverManager初始化/销毁Driver:
A.kt:
class A { @Before fun setUp() { DriverManager.initDriver() } @After fun tearDown() { DriverManager.quitDriver() } @When("Step A") fun stepA() { // 用DriverManager.webDriver访问浏览器,执行Step A的逻辑 } @Then("Result A") fun resultA() { // 结果断言逻辑 } }
B.kt(和A类结构一致):
class B { @Before fun setUp() { DriverManager.initDriver() } @After fun tearDown() { DriverManager.quitDriver() } @When("Step B") fun stepB() { // Step B的逻辑 } @Then("Result B") fun resultB() { // 结果断言逻辑 } }
这样每个场景执行前,都会通过测试类的@Before初始化Driver,公共步骤里直接用DriverManager的实例,就不会出现上下文不匹配的问题了。
方案二:用Cucumber依赖注入(PicoContainer)
如果你的项目比较复杂,推荐用依赖注入的方式,让Cucumber自动为每个场景维护一个上下文,所有步骤类共享这个上下文里的Driver。
- 先在build.gradle里添加PicoContainer依赖(版本要和你的Cucumber版本一致):
testImplementation 'io.cucumber:cucumber-picocontainer:7.14.0' // 替换成你的Cucumber版本
- 创建一个测试上下文类,用来存放Driver实例:
class TestContext { lateinit var webDriver: WebDriver }
- 所有步骤类(包括公共步骤)都通过构造函数注入TestContext:
公共步骤类CommonSteps.kt:
class CommonSteps(private val testContext: TestContext) { @Given("i am logged in") fun logInChecking() { testContext.webDriver.get("你的登录页面URL") // 登录逻辑 } }
A.kt:
class A(private val testContext: TestContext) { @Before fun setUp() { testContext.webDriver = ChromeDriver() } @After fun tearDown() { testContext.webDriver.quit() } @When("Step A") fun stepA() { // 使用testContext.webDriver执行逻辑 } // ...其他步骤 }
B.kt同理,只需要替换Step B和Result B的逻辑即可。
Cucumber会自动为每个场景创建一个独立的TestContext实例,所有关联的步骤类都会拿到同一个实例,这样Driver就会和当前场景的上下文绑定,不会出现错位的问题。
为什么之前的方法不行?
你之前把公共步骤放在A类里,当执行B.feature时,Cucumber会根据步骤匹配到A类的logInChecking方法,但此时A类的@Before注解方法并不会执行(因为@Before是属于A类的,只有执行A.feature的场景时才会触发),所以A类里的webDriver还没初始化,自然就抛出未初始化的错误了。
备注:内容来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

