【问题标题】:Step definitions in external files in BehatBehat 中外部文件中的步骤定义
【发布时间】:2011-09-11 11:26:51
【问题描述】:

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

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

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

例如

homepage.feature
HomepageContext extends FeatureContext

【问题讨论】:

    标签: php testing bdd behat


    【解决方案1】:

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

    接下来,如果您想以不同于 FeatureContext 的方式命名您的类,您可以在 behat.yml 配置文件的“Context Configuration”部分重新定义它。

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

    但你的问题也问:

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

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

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

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

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

    【讨论】:

    • 我了解您来自哪里,但您是否忘记了维护规格的痛苦? Sfisioza 的观点(我猜)是关于这个的。如果有人有一个复杂的系统,可能会经历通过单体 FeatureContext.php 的痛苦
    • 您似乎忽略了这样一个事实,即您的定义文件很快就会有 14 000 行长,无论是否是字典(我真的明白您的观点,并且完全同意您应该将其视为字典) .您也错过了您并不总是需要完整功能字典的点。是的,定义应该始终相同,但我什至需要定义吗?我怎么能确定定义没有以稍微不同的方式编写?通过拆分文件来创建订单肯定会有所帮助。
    【解决方案2】:

    使用类继承和分离上下文。

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 这仅适用于 Behat 的 2.x 版本。 useContext 方法已在 Behat 3.x 中删除。
      • Behat3 中 useContext 的替代方案是什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多