简体   繁体   English

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

[英]Step definitions in external files in Behat

Behat by default looks for the step definitions in file named FeatureContext (all steps in one file). 默认情况下,Behat会在名为FeatureContext文件中查找步骤定义(一个文件中的所有步骤)。
Having a lot of steps, it's hard to maintain such a big file. 有很多步骤,很难维护这么大的文件。

I'd like to have one definition file per feature file. 我希望每个功能文件都有一个定义文件。

How can I have step definitions in external files? 如何在外部文件中使用步骤定义?

eg 例如

homepage.feature
HomepageContext extends FeatureContext

Behat has multiple options for you to split up your FeatureContext into multiple classes. Behat有多种选项可供您将FeatureContext拆分为多个类。 First, you can use old-school php5 inheritance. 首先,你可以使用老式的php5继承。 If the inheritance is not what you want, Behat also supports subcontexts: " Using Subcontexts ". 如果继承不是你想要的,那么Behat也支持subcontexts:“ Using Subcontexts ”。

Next, if you want to name your class differently than FeatureContext , you can redefine that in " Context Configuration " section of your behat.yml config file. 接下来,如果要以与FeatureContext不同的方式命名您的类,则可以在behat.yml配置文件的“ 上下文配置 ”部分中重新定义behat.yml

This way, you could split common definitions and hooks into separate classes and use them in other feature suites as well with either subcontexting or inheritance. 这样,您可以将公共定义和挂钩拆分为单独的类,并在其他功能套件中使用它们以及子转换或继承。

But your question also asks: 但你的问题也问:

I'd like to have one definition file per feature file. 我希望每个功能文件都有一个定义文件。

This request is totally wrong. 这个要求完全错了。 Behat and Scenario BDD is all about describing your application behavior in business terms and creating test dictionary for described behaviors. Behat和Scenario BDD就是用业务术语描述您的应用程序行为并为描述的行为创建测试字典。 Keeping that in mind, you logically couldn't have multiple different dictionaries for one feature-set. 牢记这一点,您逻辑上不能为一个功能集提供多个不同的词典。 By writing step definitions, you're telling Behat what that Given I am on "/news" means. 通过编写步骤定义,你告诉Behat什么, Given I am on "/news"意思。 And when you want that step to mean different things from feature to feature - you're doing it wrong. 当你想要这个步骤从功能到功能意味着不同的东西时 - 你做错了。

Behat consists of 2 main and enough separate concepts: Behat由2个主要和足够单独的概念组成:

  1. *.feature files, written in Gherkin language. *.feature文件,用Gherkin语言编写。 Those files should be self-descriptive. 这些文件应该是自我描述的。 Means, that they should provide all the information for the reader in order to understand them. 意味着他们应该为读者提供所有信息以便理解它们。 Gherkin is not a new programming language for your functional tests, it's just a markdown for your user-stories! Gherkin不是用于功能测试的新编程语言,它只是用户故事的降价
  2. FeatureContext.php classes, describes how Behat should test your features. FeatureContext.php类,描述Behat应如何测试您的功能。 It defines application-wide dictionary to be used with whole application feature-suite. 它定义了与整个应用程序功能套件一起使用的应用程序范围的字典。 This is a programming bridge between your markdown -like user-stories and actual functional tests. 这是您的降价式用户故事和实际功能测试之间的编程桥梁。

And you shouldn't mess this things up. 你不应该搞砸这件事。 Single feature suite should have single steps dictionary (definitions). 单一功能套件应具有单步字典(定义)。 But you could use single dictionary in more than one feature suite thanks to inheritance and subcontexts. 但是由于继承和子上下文,您可以在多个功能套件中使用单个字典。 And yes, you can split single suite dictionary into multiple php classes ;-) 是的,您可以将单个套件字典拆分为多个php类;-)

Use class inheritance and separate contexts. 使用类继承和单独的上下文。

# /features/contexts/
AbstractContext extends BehatContext {}
FeaturenameContext extends AbstractContext {}

Then in /feature/FeatureContext.php import the context files: 然后在/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));
           }
        }
    }
}

One solution is horizontal reusability with subContexts. 一种解决方案是使用subContexts的水平可重用性。 Use a subContext for each "feature group". 为每个“功能组”使用subContext。

class FeatureContext extends BehatContext
{

    public function __construct(array $context_parameters)
    {
        $this->useContext('math_context', new MathContext());
        $this->useContext('bash_context', new BashContext());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM