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

发布于 2024-12-04 06:34:53 字数 242 浏览 2 评论 0 原文

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

我希望每个功能文件都有一个定义文件。

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

例如

homepage.feature
HomepageContext extends FeatureContext

Behat by default looks for the step definitions in file named FeatureContext (all steps in one file).
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?

e.g.

homepage.feature
HomepageContext extends FeatureContext

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暗藏城府 2024-12-11 06:34:53

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

接下来,如果您想以不同于 FeatureContext 的方式命名您的类,您可以在“上下文配置”部分。

这样,您可以将通用定义和挂钩拆分为单独的类,并在其他功能套件中使用它们以及子上下文或继承。

但你的问题还问:

我希望每个功能文件都有一个定义文件。

这个要求是完全错误的。行为和场景 BDD 就是用业务术语描述应用程序行为并为所描述的行为创建测试字典。记住这一点,从逻辑上讲,一个功能集不可能有多个不同的词典。通过编写步骤定义,您可以告诉 Behat Given I am on "/news" 的含义。当您希望该步骤对每个功能具有不同的含义时,您就错了。

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

  1. *.feature 文件,用 Gherkin 语言编写。这些文件应该是自我描述的。意味着他们应该为读者提供所有信息以便理解它们。 Gherkin 并不是用于功能测试的新编程语言,它只是您用户故事的降价
  2. FeatureContext.php 类,描述 Behat 应如何测试您的功能。它定义了与整个应用程序功能套件一起使用的应用程序范围字典。这是类似 ma​​rkdown 的用户故事和实际功能测试之间的编程桥梁。

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

Behat has multiple options for you to split up your FeatureContext into multiple classes. First, you can use old-school php5 inheritance. If the inheritance is not what you want, Behat also supports 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.

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. 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. 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:

  1. *.feature files, written in Gherkin language. 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!
  2. FeatureContext.php classes, describes how Behat should test your features. 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 ;-)

白衬杉格子梦 2024-12-11 06:34:53

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

# /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));
           }
        }
    }
}

Use class inheritance and separate contexts.

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

Then in /feature/FeatureContext.php import the context files:

/**
 * 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));
           }
        }
    }
}
叶落知秋 2024-12-11 06:34:53

一种解决方案是子上下文的水平可重用性。为每个“功能组”使用一个子上下文。

class FeatureContext extends BehatContext
{

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

One solution is horizontal reusability with subContexts. Use a subContext for each "feature group".

class FeatureContext extends BehatContext
{

    public function __construct(array $context_parameters)
    {
        $this->useContext('math_context', new MathContext());
        $this->useContext('bash_context', new BashContext());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文