magetest / magento-phpspec-extension
Magento PHPSpec 扩展
Requires
- php: ^7.0
- phpspec/phpspec: ^4.0 <4.1.0
- phpspec/prophecy: ^1.6
- shanethehat/pretty-xml: ~1.0.2
- symfony/config: ^3.2
- symfony/dependency-injection: ^3.2
Requires (Dev)
- behat/behat: ~3.3
- magetest/magento: ~1.8.1.0
- phpunit/phpunit: ^5.7|^6.0
- squizlabs/php_codesniffer: ^3.0
This package is not auto-updated.
Last update: 2020-01-24 19:18:26 UTC
README
安装
使用 Composer 安装
首先,将 MageSpec 添加到 composer.json
中依赖列表中,并确保注册了一些自动加载路径
{ "require-dev": { "magetest/magento-phpspec-extension": "^5.0" }, "config": { "bin-dir": "bin" }, "autoload": { "psr-0": { "": [ "public/app", "public/app/code/local", "public/app/code/community", "public/app/code/core", "public/lib" ] } } }
然后只需使用 composer 进行安装即可
$ composer install
您可以在其 官方网页 上了解更多关于 Composer 的信息。
SpecBDD 和 TDD
SpecBDD 和 TDD 之间没有真正的区别。使用 xSpec 工具代替常规 xUnit 工具进行 TDD 的价值在于语言。工具的概念和特性将使您专注于“正确”的事情。与行为和设计相比,关注验证和结构当然是一个合理的观点。我们偶然发现,从长远来看,后者更有价值。这也是 TDD 早期用户的目的。
SpecBDD 和 StoryBDD
虽然 StoryBDD 工具(如 Behat)用于理解并阐明领域 - 指定功能叙事、其需求以及我们所说的含义,但 SpecBDD 我们只关注如何实现:实现。您指定类如何实现这些功能。
一个好的 StoryBDD 工具将让业务人员使用领域语言,并通过关注真正重要的事情来驱动开发。
一旦您知道为什么要添加一个功能以及它将是什么,就几乎可以开始编写代码了。但还不是时候!在没有验证代码是否满足规格的情况下添加代码,意味着您将不得不回去重做,以确保它与规格匹配。您发现遗漏了需求或添加了错误的时间越晚,修复它就越困难、越昂贵。Kent Beck 也补充说,在编写代码之前描述代码是一种恐惧管理技巧。您不必编写所有代码,只需编写您接下来要工作的下一个东西的规格即可。这个可执行的规格将指导您需要编写什么代码。一旦您这样做,那么您拥有的就是一个重构的机会。因为如果您的代码行为发生变化,规格将变成红色。所以您编写规格是为了可以重构,或者允许代码的设计以可持续的方式出现。SpecBDD 工具旨在指导您在这个过程中,或者至少不要挡路。
假设 StoryBDD 和 SpecBDD 一起使用是一种非常有效的方法来达到高度以客户为中心的软件。
基本用法
MageSpec 已作为 PhpSpec 扩展开发,这意味着它依赖于它,并且我们需要告诉 PhpSpec 为我们加载扩展。为了做到这一点,我们必须在项目根目录中创建一个名为 phpspec.yml 的文件,并将以下内容添加到其中
extensions: MageTest\PhpSpec\MagentoExtension\Extension: ~
然而这还不够。由于 Magento 使用非标准惯例存储控制器、模型、助手等,MageSpec 实现了一个自定义的 PhpSpec 定位器服务。这种定位器必须根据我们的项目配置进行适当配置,这意味着我们还需要添加一些 'mage_locator' 配置,如下所示
extensions: MageTest\PhpSpec\MagentoExtension\Extension: mage_locator: src_path: public/app/code spec_path: spec/public/app/code
目前 mage_locator 支持五个选项
- namespace (默认 ''): 我们源代码的基本命名空间
- spec_prefix (默认 'spec'): 用于基于源代码命名空间命名规格的命名空间前缀
- src_path (默认 'src'): 源代码的相对路径
- spec_path (默认 '.'): 规格的相对路径
- code_pool (默认 'local'): 指定创建扩展文件的 Magento 代码池。选项是 'local' 和 'community'
描述一个模型
假设我们正在构建一个模块,该模块会告诉我们某个产品是否有现有的评论。我们将先从简单的事情做起,并设计出一个能够涵盖所有必要功能的方案。尽管我拥有客户的所有规格(我们完成了所有 Behat 功能文件),但我知道当我坐下来编写类时,我将会发现新的需要。
我最想添加的最简单的事情是什么?它应该告诉我一个产品是否有评论。
所以让我们这样做。嗯,不是无聊的部分。让 MageSpec 来处理无聊的事情。我们只需要告诉 MageSpec 我们将工作在 Review 模块的产品类上。所以运行以下命令
$ bin/phpspec describe:model 'magespec_reviews/product'
应该给出以下输出
Specification for MageSpec_Reviews_Model_Product created in [...]/spec/public/app/code/local/MageSpec/Reviews/Model/ProductSpec.php
好的。我们刚才做了什么?MageSpec 已经根据标准的 Magento 惯例为我们创建了规格。您可以导航到规格文件夹并查看那里的规格
<?php namespace spec; use PhpSpec\ObjectBehavior; use Prophecy\Argument; class MageSpec_Reviews_Model_ProductSpec extends ObjectBehavior { function it_is_initializable() { $this->shouldHaveType('MageSpec_Reviews_Model_Product'); } }
太棒了!MageSpec 为我创建了规格。
但首先,让我们看看这里有什么。我们的规格扩展了特殊的 ObjectBehavior 类。这个类很特殊,因为它让您能够调用您正在描述的类的所有方法,并将操作的结果与您的期望进行匹配。
示例
对象行为由示例组成。示例被包含在公共方法中,以 it_ 或 its_ 开头。phpspec 会搜索您的规范以运行这些方法。为什么示例名称要以下划线开头?只是为了使其比一些LongCamelCasingLikeThat更容易阅读。
匹配器
匹配器与 xUnit 中的断言非常相似,除了匹配器专注于说明对象应该如何表现,而不是验证其如何工作。它更好地表达了关注行为,并更适合测试驱动周期。目前 phpspec 中有 5 个匹配器,但几乎每个匹配器都有一个别名,使您的示例读起来更加流畅
- Identity (return, be, equal, beEqualTo) - 它类似于检查 ===
- Comparison (beLike) - 它类似于检查 ==
- Throw (throw -> during) - 用于测试异常
- Type (beAnInstanceOf, returnAnInstanceOf, haveType) - 检查对象类型
- ObjectState (have**) - 检查对象是否是**方法返回值
您如何使用这些?您只需在它们前面加上 should 或 shouldNot,具体取决于您的期望,然后在感兴趣的主题上调用它们。
现在我们准备继续前进。让我们更新第一个示例以表达我的下一个意图
<?php namespace spec; use PhpSpec\ObjectBehavior; use Prophecy\Argument; class MageSpec_Reviews_Model_ProductSpec extends ObjectBehavior { // ... function it_tells_if_a_product_has_reviews() { $this->load('SKU'); $this->hasReviews()->shouldReturn(true); } // ... }
现在怎么办?我们运行规格。您可能不会相信,但 MageSpec 会理解我们正在描述一个不存在的类,并建议创建它!
$ bin/phpspec MageSpec_Reviews_Model_Product 10 ! it is initializable class MageSpec_Reviews_Model_Product does not exists. -----------------------100%----------------------- 1 1 example (1 broken) 11ms Do you want me to create `MageSpec_Reviews_Model_Product` for you? [Y/n] Model MageSpec_Reviews_Model_Product created in [...]/public/app/code/local/MageSpec/Reviews/Model/Product.php.
MageSpec 现在已经将空类放入了目录中。
<?php class MageSpec_Reviews_Model_Product extends Mage_Core_Model_Abstract { }
您再次运行规格,然后... 好的,您猜对了
$ bin/phpspec MageSpec_Reviews_Model_Product 15 ! it tells if a product has reviews method MageSpec_Reviews_Model_Product::load() not found. -----------------------97%----------------------- 2 2 examples (1 passed, 1 broken) 12ms Do you want me to create `MageSpec_Reviews_Model_Product::load()` for you? [Y/n] Method MageSpec_Reviews_Model_Product::load() has been created.
然后...
$ bin/phpspec MageSpec_Reviews_Model_Product 15 ! it tells if a product has reviews method MageSpec_Reviews_Model_Product::hasReviews() not found. -----------------------97%----------------------- 2 @ examples (1 passed, 1 broken) 12ms Do you want me to create `MageSpec_Reviews_Model_Product::hasReviews()` for you? [Y/n] Method MageSpec_Reviews_Model_Product::hasReviews() has been created
我们刚才做的事情是快速通过琥珀状态进入红色状态。如果您检查您的类,您现在应该看到类似这样的内容
<?php class MageSpec_Reviews_Model_Product extends Mage_Core_Model_Abstract { public function load($argument1) { // TODO: write logic here } public function hasReviews() { // TODO: write logic here } }
我们消除了由于不存在类和方法导致的致命错误和丑陋的消息,并直接进入了真正的失败规范。
$ bin/phpspec
MageSpec_Reviews_Model_Product
15 ✘ it tells if a product has reviews
expected true, but got null.
-----------------------97%----------------------- 2
2 examples (1 passed, 1 failed)
11ms
根据TDD规则,我们现在有充分的权限来编写代码。红色表示“是时候添加代码”了;红色太棒了!现在我们添加足够的代码,快速地将规范变为绿色。我们会有时间使其正确,但首先让它变为绿色。
<?php class MageSpec_Reviews_Model_Product { public function load($argument1) { // TODO: write logic here } public function hasReviews() { return true; } }
看看吧!
$ bin/phpspec ----------------------100%----------------------- 2 2 example (2 passed) 11ms
如果你对PHP中的规范感兴趣,最好查看官方PhpSpec页面,或者,如果你对整个TDD/SpecBDD循环更感兴趣,已经有大量的资源了。这里为你提供一些供参考:
- 《Rspec Book:使用RSpec、Cucumber和朋友的开发》由David Chelimsky、Dave Astels、Zach Dennis、Aslak Hellesøy、Bryan Helmkamp、Dan North所著
- 《测试驱动开发:示例》由Kent Beck所著
额外支持的命令
截至今天,MageSpec目前允许你描述不同的Magento类。以下是一个简要列表。
描述一个块
$ bin/phpspec describe:block 'vendorname_modulename/blockname'
描述一个辅助函数
$ bin/phpspec describe:helper 'vendorname_modulename/helpername'
描述一个控制器
$ bin/phpspec describe:controller 'vendorname_modulename/helpername'
问题提交
在您提交一个新问题之前,请确保您已经阅读了问题提交指南。
贡献
请参阅贡献文档
许可和作者
作者:https://github.com/MageTest/MageSpec/contributors
版权(C)2012-2013
在此特此授予任何获得此软件及其相关文档副本(以下简称“软件”)的人免费使用该软件的权利,不受限制地处理该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本,并允许向提供软件的人提供使用该软件的权利,前提是遵守以下条件:
上述版权声明和本许可声明应包含在所有副本或实质部分中。
软件按“原样”提供,不提供任何形式的保证,无论是明示的、暗示的,还是关于适销性、特定用途适用性或非侵权性的保证。在任何情况下,作者或版权所有者不对任何索赔、损害或其他责任(无论因合同、侵权或其他原因引起)承担责任,即使已经被告知该软件或其使用可能引起此类损害。