如何组织Behat的Features目录与Context类以复用相同步骤?
Behat 通用步骤重复定义问题解决
我有2个Feature,每个Feature对应一个Context类(RegisterVehcileContext和ParkVehicleContext)。这两个Feature存在通用步骤,因此我创建了Trait来存放这些步骤,但Behat提示「步骤已定义」的错误。我可以在各Context中重复编写通用步骤并改用不同名称,但不愿重复代码。
(错误提示截图:显示Behat报错步骤已被多个上下文重复定义)
我的behat.yml配置如下:
default: suites: web: contexts: - RegisterVehcileContext - ParkVehicleContext
解决方案
方案1:抽离通用步骤为独立Context
Behat允许在Suite中加载多个Context,你可以把通用步骤放到独立的CommonContext类中,直接在配置里引入这个Context,无需用Trait混入业务Context:
修改behat.yml:
default: suites: web: contexts: - CommonContext - RegisterVehcileContext - ParkVehicleContext
CommonContext示例代码:
use Behat\Behat\Context\Context; class CommonContext implements Context { /** * @Given 我已登录系统 */ public function iAmLoggedIn() { // 通用步骤逻辑实现 } }
这种方式下,Behat会自动识别所有Context中的步骤,不会出现重复定义问题,同时完全避免代码重复。
方案2:Trait复用时避免重复加载
如果坚持使用Trait,需要确保同一个Trait不会被多个Context同时加载到同一个Suite中:
- 仅将Trait混入到一个业务Context,其他Context通过依赖注入调用该Context的通用方法
- 拆分Suite,让每个Suite中只有一个Context使用该Trait
方案3:通过方法调用复用逻辑(不推荐)
在业务Context中调用通用步骤的逻辑,而非直接复用注解:
比如在ParkVehicleContext中:
use Behat\Behat\Context\Context; use RegisterVehcileContext; class ParkVehicleContext implements Context { private $registerContext; public function __construct(RegisterVehcileContext $registerContext) { $this->registerContext = $registerContext; } /** * @Given 我已登录系统 */ public function iAmLoggedIn() { $this->registerContext->iAmLoggedIn(); } }
这种方式仍可能触发步骤重复定义提示,仅作为临时替代方案。
内容的提问来源于stack exchange,提问作者Olivier Meunier
相关产品推荐
相关产品推荐

