mgeoffray/magento-behat-extension

Magento Behat 扩展

1.0.2 2017-07-27 15:21 UTC

README

Build Status Scrutinizer Code Quality

为 Magento 提供的 Behat 扩展,它提供了符合特定 Magento 要求的 Behat 上下文,允许您快速定义 Magento 场景和步骤,以在 Magento 项目中启用 BDD。

目标

  • 创建一个使测试变得简单且易于使用的工具,以便测试 Magento 的外部行为。
  • 创建一个工具,在抛出异常时提供清晰的反馈。反馈应指导开发者如何解决问题,并且信息应与 Magento 域正确对应。

如何实现?

  • 该工具可以通过 composer 轻松安装。
  • 无需创建新上下文即可完成标准场景的创建。
  • 不会抛出不提供如何继续或解决问题的反馈的异常。
  • 文档包含使用工具每个功能的示例。

安装

先决条件

BehatMage 需要 PHP 5.3.x 或更高版本。

使用 composer 安装

对于本文档,我们假设目录布局如下。

project-dir
├── behat.yml
├── bin
│   └── behat
├── composer.json
├── composer.lock
├── features
│   ├── bootstrap
│   └── ...
├── htdocs
│   ├── app
│   ├── downloader
│   ├── index.php
│   ├── js
│   ├── skin
│   ├── var
│   └── ...
└── vendor
    ├── autoload.php
    ├── behat
    ├── magetest
    └── ...

我们假设您将保留 behat 功能声明,并将从项目目录(在 Magento 基础目录之上)调用 behat 脚本。当然,任何其他布局也是可能的。请注意以下调整:

  • behat.yml 文件需要放在调用 behat 脚本的目录中。
  • composer.json PSR-0 自动加载路径声明需要调整。
  • behat.yml 中默认的 paths.features 设置需要调整。

首先,将 BehatMage 添加到 composer.json 中的依赖列表中,并确保注册几个自动加载路径

{
    "config": {
        "bin-dir": "bin"
    },
    "require": {
        "php": ">=5.3.0"
    },
    "require-dev": {
        "magetest/magento-behat-extension": "feature/Behat3"
    },
    "autoload": {
        "psr-0": {
            "": [
                "htdocs/app",
                "htdocs/app/code/local",
                "htdocs/app/code/community",
                "htdocs/app/code/core",
                "htdocs/lib"
            ]
        }
    },
    "minimum-stability": "dev"
}

然后使用 composer 安装它

$ composer install --dev --prefer-dist

您可以在其官方网站上了解更多关于 Composer 的信息。

基本用法

切换到您的项目目录,并在该目录中设置 behat

$ cd project
$ bin/behat --init

behat --init 将创建一个 features/ 目录,其中包含一些基本内容以帮助您开始。屏幕上的输出应类似于

$ bin/behat --init
+d features - place your *.feature files here
+d features/bootstrap - place bootstrap scripts and static files here
+f features/bootstrap/FeatureContext.php - place your feature related code here

定义您的功能

Behat 中的一切始终从一个您想描述并实现的特性开始。在本例中,特性将赋予管理员用户管理可见性的能力,因此我们可以从创建 features/admin_user_manages_review_visibility.feature 文件开始

Feature: Admin User can manage review visibility
    So that our Customers are not influenced by a product with bad review history,
    as an Admin User
    I want to disable reviews of those specific products

每个特性都以相同的格式开始:一行命名特性,然后是三行描述好处、角色和特性本身。虽然这一部分是必需的,但它的内容对 Behat 或您最终进行的测试并不重要。然而,这一部分很重要,以确保每个特性都一致地描述并且可供其他人阅读。

定义场景

接下来,将以下场景添加到 features/admin_user_manages_review_visibility.feature 文件的末尾

Scenario: Turn off reviews per product
    Given the following products exist:
        | sku      | name           | accepts_reviews |
        | Ottoman1 | Ottoman        | 1               |
    And "Ottoman1" has existing reviews
    When I turn reviews off for "Ottoman1" product
    Then no review should be displayed for "Ottoman1"

每个特性由一个或多个“场景”定义,这些场景解释了该特性在不同条件下的行为方式。这部分将被转换成测试。每个场景始终遵循相同的格式

Scenario: Some description of the scenario
    Given [some context]
    When [some event]
    Then [outcome]

场景的每个部分 - 上下文、事件和结果 - 都可以通过添加 And 或 But 关键字进行扩展

Scenario: Some description of the scenario
    Given [some context]
        And [more context]
    When [some event]
        And [second event occurs]
    Then [outcome]
        And [another outcome]
        But [another outcome]

Then、And But 或任何以单词开头的行为关键字之间没有实际的区别。这些关键字都提供给了您,以便您的场景既自然又易于阅读。

执行 Behat

您已经定义了功能及其一个场景。现在您准备好见证Behat的功能了!尝试在您的项目目录下执行Behat。

$ bin/behat

如果一切正常,您应该看到如下内容

Feature: Admin User can manage review visibility
  So that our Customers are not influenced by a product with bad review history,
  as an Admin User
  I want to disable reviews of those specific products

  Scenario: Turn off reviews per product              # features/reviews/admin_user_manages_review_visibility.feature:7
    Given the following products exist:
      | sku      | name    | accepts_reviews |
      | Ottoman1 | Ottoman | 1               |
    And "Ottoman1" has existing reviews
    When I turn reviews off for "Ottoman1" product
    Then no review should be displayed for "Ottoman1"

1 scenario (1 undefined)
4 steps (4 undefined)
0m1.836s

You can implement step definitions for undefined steps with these snippets:

    /**
     * @Given /^the following products exist:$/
     */
    public function theFollowingProductsExist(TableNode $table)
    {
        throw new PendingException();
    }

    /**
     * @Given /^"([^"]*)" has existing reviews$/
     */
    public function hasExistingReviews($arg1)
    {
        throw new PendingException();
    }

    /**
     * @When /^I turn reviews off for "([^"]*)" product$/
     */
    public function iTurnReviewsOffForProduct($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then /^no review should be displayed for "([^"]*)"$/
     */
    public function noReviewShouldBeDisplayedFor($arg1)
    {
        throw new PendingException();
    }

编写您的步骤定义

Behat自动找到feature/admin_user_manages_review_visibility.feature文件,并尝试将其场景作为测试执行。然而,我们还没有告诉Behat如何处理诸如“Given以下产品存在”这样的语句,这会导致错误。Behat通过将场景的每个语句与您定义的正则表达式“步骤”列表进行匹配来工作。换句话说,告诉Behat在看到“Given以下产品存在”时该做什么是您的责任。幸运的是,Behat会帮您打印出创建该步骤定义可能需要的正则表达式。

You can implement step definitions for undefined steps with these snippets:

    /**
     * @Given /^the following products exist:$/
     */
    public function theFollowingProductsExist(TableNode $table)
    {
        throw new PendingException();
    }

    /**
     * @Given /^"([^"]*)" has existing reviews$/
     */
    public function hasExistingReviews($arg1)
    {
        throw new PendingException();
    }

    /**
     * @When /^I turn reviews off for "([^"]*)" product$/
     */
    public function iTurnReviewsOffForProduct($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then /^no review should be displayed for "([^"]*)"$/
     */
    public function noReviewShouldBeDisplayedFor($arg1)
    {
        throw new PendingException();
    }

然而,Behat目前还没有意识到Magento域,并要求我们添加我们可能因为其重复性而希望跳过的步骤定义。然后我们必须使用配置文件behat.yml使Behat意识到Magento,添加以下行

default:
  extensions:
    MageTest\MagentoExtension\Extension:
      base_url: "http://project.development.local"

  # The default is to have the features directory inside the project directory
  # If you want the features directory inside the Magento installation, set paths.features:
  #paths:
  #  features: htdocs/features

在这里,我们告诉Behat要加载哪个扩展以及我们想要测试哪个商店。

到目前为止做得很好,现在我们必须告诉Behat,为了清晰起见,我们想要为每个角色使用特定的子上下文,在我们的例子中是管理员用户。为了做到这一点,我们必须更新features/bootstrap/FeatureContext.php文件,如下所示

<?php
# features/bootstrap/FeatureContext.php

use Behat\Behat\Context\ClosuredContextInterface,
    Behat\Behat\Context\TranslatedContextInterface,
    Behat\Behat\Context\BehatContext,
    Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
    Behat\Gherkin\Node\TableNode;

//
// Require 3rd-party libraries here:
//
//   require_once 'PHPUnit/Autoload.php';
//   require_once 'PHPUnit/Framework/Assert/Functions.php';
//

/**
 * Features context.
 */
class FeatureContext extends BehatContext
{
    /**
     * Initializes context.
     * Every scenario gets it's own context object.
     *
     * @param array $parameters context parameters (set them up through behat.yml)
     */
    public function __construct(array $parameters)
    {
        // Initialize your context here
        $this->useContext('admin_user', new AdminUserContext($parameters));
    }
}

然后创建这样的子上下文,作为BehatMage扩展提供的MagentoContext的PHP类扩展,如下所示

<?php
# features/bootstrap/AdminUserContext.php

use Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\TableNode;
use MageTest\MagentoExtension\Context\MagentoContext;

class AdminUserContext extends MagentoContext
{

}

如果我们再次运行Behat,现在框架已经意识到了Magento域,我们的输出应该不同,看起来像这样

Feature: Admin User can manage review visibility
  So that our Customers are not influenced by a product with bad review history,
  as an Admin User
  I want to disable reviews of those specific products

  Scenario: Turn off reviews per product              # features/reviews/admin_user_manages_review_visibility.feature:7
    Given the following products exist:               # AdminUserContext::theProductsExist()
      | sku      | name    | accepts_reviews |
      | Ottoman1 | Ottoman | 1               |
      accepts_reviews is not yet defined as an attribute of Product
    And "Ottoman1" has existing reviews
    When I turn reviews off for "Ottoman1" product
    Then no review should be displayed for "Ottoman1"

1 scenario (1 failed)
4 steps (3 undefined, 1 failed)
0m1.481s

You can implement step definitions for undefined steps with these snippets:

    /**
     * @Given /^"([^"]*)" has existing reviews$/
     */
    public function hasExistingReviews($arg1)
    {
        throw new PendingException();
    }

    /**
     * @When /^I turn reviews off for "([^"]*)" product$/
     */
    public function iTurnReviewsOffForProduct($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then /^no review should be displayed for "([^"]*)"$/
     */
    public function noReviewShouldBeDisplayedFor($arg1)
    {
        throw new PendingException();
    }

如您所见,添加以下片段的建议已经消失

    /**
     * @Given /^the following products exist:$/
     */
    public function theFollowingProductsExist(TableNode $table)
    {
        throw new PendingException();
    }

这是因为BehatMage已经提供了所有这些常见步骤的实现,这些步骤通常需要测试Magento行为。所以现在让我们使用Behat的建议,并将以下内容添加到features/bootstrap/AdminUserContext.php文件中

<?php
# features/bootstrap/AdminUserContext.php

use Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\TableNode;
use MageTest\MagentoExtension\Context\MagentoContext;

class AdminUserContext extends MagentoContext
{
    /**
     * @Given /^"([^"]*)" has existing reviews$/
     */
    public function hasExistingReviews($arg1)
    {
        throw new PendingException();
    }

    /**
     * @When /^I turn reviews off for "([^"]*)" product$/
     */
    public function iTurnReviewsOffForProduct($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then /^no review should be displayed for "([^"]*)"$/
     */
    public function noReviewShouldBeDisplayedFor($arg1)
    {
        throw new PendingException();
    }
}

或者使用以下命令行选项让Behat为我们完成

$ bin/behat --append-to=AdminUserContext

太棒了!现在您已经定义了所有步骤并告诉Behat要使用哪个上下文,再次运行Behat

$ bin/behat

如果一切正常,您应该看到如下内容

Feature: Admin User can manage review visibility
  So that our Customers are not influenced by a product with bad review history,
  as an Admin User
  I want to disable reviews of those specific products

  Scenario: Turn off reviews per product              # features/reviews/admin_user_manages_review_visibility
    Given the following products exist:               # AdminUserContext::theProductsExist()
      | sku      | name    | accepts_reviews |
      | Ottoman1 | Ottoman | 1               |
      accepts_reviews is not yet defined as an attribute of Product
    And "Ottoman1" has existing reviews               # AdminUserContext::hasExistingReviews()
    When I turn reviews off for "Ottoman1" product    # AdminUserContext::iTurnReviewsOffForProduct()
    Then no review should be displayed for "Ottoman1" # AdminUserContext::noReviewShouldBeDisplayedFor()## Some more about Behat basics

如您所见,由于BehatMage扩展,Behat为开发者提供了有关下一步要执行的有意义和有用的信息。因此,让我们添加必要的代码以使我们的步骤的第一个要求通过。根据建议的代码创建以下文件

<?xml version="1.0"?>
<!-- app/code/local/BehatMage/Catalog/etc/config.xml -->
<config>
    <modules>
        <BehatMage_Catalog>
            <version>0.1.0</version>
            <depends>
                <Mage_Catalog />
            </depends>
        </BehatMage_Catalog>
    </modules>
    <global>
        <resources>
            <behatmage_catalog_setup>
                <setup>
                    <module>BehatMage_Catalog</module>
                    <class>Mage_Catalog_Model_Resource_Setup</class>
                </setup>
            </behatmage_catalog_setup>
        </resources>
    </global>
</config>
<?xml version="1.0"?>
<!-- app/etc/modules/BehatMage_Catalog.xml -->
<config>
    <modules>
        <BehatMage_Catalog>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Catalog />
            </depends>
        </BehatMage_Catalog>
    </modules>
</config>
<?php
# app/code/local/BehatMage/Catalog/data/behatmage_catalog_setup/data-install-0.1.0.php

/** @var Mage_Catalog_Model_Resource_Setup $this */
$installer = $this;

$installer->startSetup();

$installer->addAttribute('catalog_product', 'accepts_reviews', array(
    'group' => 'General',
    'input' => 'boolean',
    'type' => 'int',
    'label' => 'Accept Reviews',
    'default' => true,
    'user_defined' => true,
    'visible_on_front' => true,
    'visible_in_advanced_search' => false,
    'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
));

$installer->endSetup();

一旦创建了文件,清除Magento缓存以运行设置脚本并添加所需的属性。现在是再次运行Behat的时候了

$ bin/behat

如果一切顺利,您的输出现在应该是这样的

Feature: Admin User can manage review visibility
  So that our Customers are not influenced by a product with bad review history,
  as an Admin User
  I want to disable reviews of those specific products

  Scenario: Turn off reviews per product              # features/reviews/admin_user_manages_review_visibility.feature:7
    Given the following products exist:               # AdminUserContext::theProductsExist()
      | sku      | name    | accepts_reviews |
      | Ottoman1 | Ottoman | 1               |
    And "Ottoman1" has existing reviews               # AdminUserContext::hasExistingReviews()
      TODO: write pending definition
    When I turn reviews off for "Ottoman1" product    # AdminUserContext::iTurnReviewsOffForProduct()
    Then no review should be displayed for "Ottoman1" # AdminUserContext::noReviewShouldBeDisplayedFor()

1 scenario (1 pending)
4 steps (1 passed, 2 skipped, 1 pending)
0m6.478s

如您所见,现在我们的产品定义有了所需的属性,Behat已经移动到场景的下一个步骤。想象一下,现在我们只需要逐步实现所有必需的测试和代码,以符合之前定义的场景。

关于功能的更多内容

关于步骤的更多内容

上下文类:MagentoContext

BehatMage命令行工具

接下来是什么?

问题提交

在您打开新问题之前,请确保您已经阅读了问题提交指南

贡献

查看贡献文档

许可证和作者

作者:https://github.com/MageTest/BehatMage/contributors

版权(C)2012-2013

本软件及其相关文档文件(以下简称“软件”)的使用权、复制权、修改权、合并权、发布权、分发权、再许可权和/或销售副本的权利,以及允许获得软件副本的个人在不限制的前提下使用该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许将软件提供给他人进行上述操作,但需遵守以下条件:

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何形式的质量保证,无论是明示的、暗示的还是其他形式的,包括但不限于适销性、特定用途的适用性和非侵权性保证。在任何情况下,作者或版权所有者不应对任何索赔、损害或其他责任负责,无论该责任源于合同行为、侵权行为或其他,包括但不限于与软件或其使用或其他方式相关的软件。