Magento 1.9中单元测试的最佳实践


11

我维护了带有多个自定义模块的Magento 1.9网站。其中一些功能对业务至关重要,并且迫切需要一些单元测试。例如,单价计算器。

我通常在Symfony中进行开发,并且如果可能的话,我真的更愿意以某种方式使用PHPUnit(w / Composer)。

一些功能基于导入到几个自定义数据库表中的数据,因此我宁愿以某种方式加载固定装置。

因此,我正在寻找编写一些单元测试的最佳实践方法。我乐意接受教程或类似的东西。任何帮助表示赞赏。

Answers:


10

我前段时间也遇到了同样的问题。

我考虑过使用Ecomdev PHPUnit模块,但是我发现它很难使用且文档记录不充分(但是我仍然喜欢Ivan所做的事情以及他对Magento生态系统的巨大贡献)。

因此,在Vinai的帮助下,我最终开发了以下测试框架模块:https : //github.com/digitalpianism/testframework

最初的目的是用于集成测试,但我也将其用于单元测试。您可以在此处查看它的运行情况:https : //github.com/digitalpianism/easytoplinks/blob/master/app/code/community/DigitalPianism/EasyToplinks/Test/Unit/Block/Page/Template/LinksTest.php

关于固定装置,我正在使用事务回滚以避免在数据库中创建样本数据。


这看起来确实很有希望。我会尝试一下。谢谢。
frigg's

13

安装

由于Magento 1并没有开箱即用,因此如果您使用composer安装phpunit或仅下载phar版本,我认为这没有太大的区别。
如果您已经使用composer来管理站点中的其他第三方模块或库,那么composer可能最有意义。除非您使用PHP7,否则您将只能使用旧版本的phpunit(这就是我链接到上述4.8版本的原因)。

集成测试与/和/或单元测试

由于Magento 1是如此繁重的应用程序,因此将phpunit bootstrap分为一个用于集成和一个用于单元测试是有意义的。
单元测试引导程序仅需要初始化自动加载器,而集成测试引导程序则需要初始化整个应用程序环境,包括配置加载和数据库连接。
因此,Magento中的集成测试往往比单元测试要慢得多(在其他应用程序中则要慢得多)。

将Magento引导到phpunit

  • Magento的自动加载器不符合PSR-0,因为如果找不到类所在的文件,它将抛出异常。这会中断class_existsphpunit中的某些用法。有几种可能的解决方法:

    • 取消注册Magento自动装带器,将其包装\Varien_Autoload::autoload()在装饰器中,而忽略其中引发的异常,然后将包装器注册为新的自动装带器。与注册自动加载器并依赖于特定自动加载器顺序的第三方库发生冲突的可能性很小。
    • 使用自定义错误处理程序包装Magento 1中内置的错误处理程序。自定义错误处理程序将吞噬Magento自动加载器触发的错误。这是Raphael的测试框架使用的解决方案。这似乎与其他第三方扩展最兼容。
    • \Varien_Autoload::autoload()如果文件不存在,请使用include路径hack重写以不引发错误。但是,这与也覆盖相同类的几个模块冲突。我自己不使用这种方法。
  • 为了避免在测试期间启动会话时出错,只需$_SESSON = []在引导程序中进行设置即可。

  • 设置自定义响应对象Mage::app()->setResponse($testResponse),以扩展真实对象,但不发送输出或标头。

  • 要在完全更改运行时状态的集成测试之间重新初始化Magento,请使用Mage::reset(); Mage::app()。请注意,此后必须重新装饰错误处理程序。

治具

对于DB固定装置,我倾向于在固定装置方法中使用常规模型来创建固定装置,例如createSimpleProduct($sku)。就像Raphael所说的那样,使用setUp()tearDown()将测试包装在一个事务中,该事务在测试之后会回滚(例如Mage::getSingleton('core/resource')->getConnection('default_setup')->beginTransaction())。

对于商店配置固定装置,我倾向于使用设置内存中固定装置Mage::app()->getStore()->setConfig($path, $value)

EcomDev_PHPUnit扩展还提供了使用yaml文件创建DB固定装置的选项,但是对于我自己来说,与使用模型类创建的固定装置相比,我发现这些装置更难以维护。YMMV。

测试双打

注册表可以用于注入测试双打通过创建的对象Mage::getSingleton()Mage::getResourceSingleton()Mage::helper()
可以设置其他一些中心对象Mage::app()(例如请求)。
要替换通过测试双打Mage::getModel()Mage::getResourceModel()通过测试双打创建的类,必须使用自定义配置对象包装。请参见拉斐尔(Raphael)的测试框架中的示例该操作如何完成。

摘要

一旦启动了Magento,几乎可以对所有内容进行很好的测试。由于核心代码使用了大量方法链接,因此请准备好创建深层模拟。
即使安装程序很笨拙,也可以正常工作,我发现测试给了我很多信心和价值,几乎可以与Symphony应用程序的测试套件相提并论。


我从未尝试过,但是为什么不使用Magento Test Framework?(docs.magento.com/m1/ce/user_guide/magento/...
弗拉

3
是的,我已经尝试过了,但是它是功能测试(不是单元或集成),它很慢,很复杂,并且测试往往很脆弱。总而言之,我认为我花费的时间是浪费。
维奈

@Vinai我知道它来晚了,但是通常在控制器中有对模型和集合的调用,而在测试时我们不需要。我正在使用您的测试框架(DigitalPianism),我们可以对模型进行Double建模,但是在对使用模型的控制器操作发出get请求时,如何模拟该模型/集合调用?
arqam '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.