Php Behat中外部文件中的步骤定义

Php Behat中外部文件中的步骤定义,php,testing,bdd,behat,Php,Testing,Bdd,Behat,默认情况下,Behat在名为FeatureContext的文件中查找步骤定义(所有步骤都在一个文件中)。 有很多步骤,很难维护这么大的文件 我希望每个要素文件有一个定义文件 如何在外部文件中定义步骤 e、 g Behat有多个选项可供您将FeatureContext拆分为多个类。首先,可以使用老式的php5继承。如果继承不是您想要的,则Behat还支持子文本:“” 接下来,如果您想将类命名为不同于FeatureContext,可以在behat.yml配置文件的“”部分中重新定义 通过这种方式,您

默认情况下,Behat在名为
FeatureContext
的文件中查找步骤定义(所有步骤都在一个文件中)。
有很多步骤,很难维护这么大的文件

我希望每个要素文件有一个定义文件

如何在外部文件中定义步骤

e、 g


Behat有多个选项可供您将FeatureContext拆分为多个类。首先,可以使用老式的php5继承。如果继承不是您想要的,则Behat还支持子文本:“”

接下来,如果您想将类命名为不同于
FeatureContext
,可以在
behat.yml
配置文件的“”部分中重新定义

通过这种方式,您可以将常见的定义和钩子拆分为单独的类,并在其他功能套件中使用它们,也可以将它们与分包或继承一起使用

但你的问题也会问:

我希望每个要素文件有一个定义文件

这个要求是完全错误的。Behat和Scenario BDD都是关于用业务术语描述应用程序行为,并为所描述的行为创建测试字典。记住这一点,从逻辑上讲,一个功能集不能有多个不同的词典。通过编写步骤定义,您可以告诉Behat,鉴于我在“/news”上,这是什么意思。当你想让这一步从一个功能到另一个功能意味着不同的东西时,你就错了

Behat由两个主要且足够独立的概念组成:

  • *。功能
    文件,用小黄瓜语言编写。这些文件应该是自描述性的。也就是说,他们应该为读者提供所有信息,以便读者理解他们。Gherkin不是一种用于功能测试的新编程语言,它只是用户故事的一种标记
  • FeatureContext.php
    classes,描述了Behat应该如何测试您的功能。它定义了要与整个应用程序功能套件一起使用的应用程序范围的字典。这是降价类用户故事和实际功能测试之间的编程桥梁

  • 你不应该把事情搞砸。单个功能套件应具有单个步骤字典(定义)。但由于继承和子文本,您可以在多个功能套件中使用单个字典。是的,您可以将单个套件字典拆分为多个php类;-)

    使用类继承和单独的上下文

    # /features/contexts/
    AbstractContext extends BehatContext {}
    FeaturenameContext extends AbstractContext {}
    
    然后在
    /feature/FeatureContext.php
    中导入上下文文件:

    /**
     * Initializes context.
     * Every scenario gets it's own context object.
     *
     * @param array $parameters context parameters (set up via behat.yml)
     */
    public function __construct(array $parameters) {
    
        // import all context classes from context directory, except the abstract one
    
        $filesToSkip = array('AbstractContext.php');
    
        $path = dirname(__FILE__) . '/../contexts/';
        $it = new RecursiveDirectoryIterator($path);
        /** @var $file  SplFileInfo */
        foreach ($it as $file) {
            if (!$file->isDir()) {
               $name = $file->getFilename();
               if (!in_array($name, $filesToSkip)) {
                   $class = pathinfo($name, PATHINFO_FILENAME);
                   require_once dirname(__FILE__) . '/../context/' . $name;
                   $this->useContext($class, new $class($parameters));
               }
            }
        }
    }
    

    一种解决方案是对子上下文的水平重用。为每个“要素组”使用子上下文


    我知道你从哪里来,但你忘记了维护规格的痛苦吗?Sfisoza的观点(我想)是关于这一点的。如果有人有一个复杂的系统,你可能会经历通过单片FeatureContext的痛苦。phpy你似乎忽视了一个事实,即你的定义文件很快就会有14000行长,不管是否是字典(我真的明白你的观点,并且完全同意你应该把它看作字典)。您还忽略了一点,即您并不总是需要完整的功能字典。是的,定义应该总是一样的,但是我需要定义吗?我怎么能确定这个定义没有以稍微不同的方式写成呢?在这里,通过拆分文件来创建订单肯定会有所帮助。这仅适用于2.x版本的Behat。Behat 3.x中的
    useContext
    方法已被删除。Behat3中useContext的替代方法是什么?
    /**
     * Initializes context.
     * Every scenario gets it's own context object.
     *
     * @param array $parameters context parameters (set up via behat.yml)
     */
    public function __construct(array $parameters) {
    
        // import all context classes from context directory, except the abstract one
    
        $filesToSkip = array('AbstractContext.php');
    
        $path = dirname(__FILE__) . '/../contexts/';
        $it = new RecursiveDirectoryIterator($path);
        /** @var $file  SplFileInfo */
        foreach ($it as $file) {
            if (!$file->isDir()) {
               $name = $file->getFilename();
               if (!in_array($name, $filesToSkip)) {
                   $class = pathinfo($name, PATHINFO_FILENAME);
                   require_once dirname(__FILE__) . '/../context/' . $name;
                   $this->useContext($class, new $class($parameters));
               }
            }
        }
    }
    
    class FeatureContext extends BehatContext
    {
    
        public function __construct(array $context_parameters)
        {
            $this->useContext('math_context', new MathContext());
            $this->useContext('bash_context', new BashContext());
        }
    }