为Magento 2模块创建集成测试


27

到目前为止,为了满足Magento 2的测试需求,我一直在使用PHP Unit(或多或少)作为验收测试器-测试服务器和HTML请求的结果,这些请求是在安装了模块的系统中进行的。我希望能够创建自己的集成测试。Magento 2附带的测试工具是否允许第三方开发人员利用Magento的测试框架代码创建自己的集成测试?还是我们都将推出自己的引导程序?

那是

  1. 我是Magento开发人员
  2. 我想创建一个集成测试
  3. 我要在集成测试中使用完全引导的Magento环境(例如,使用对象管理器和/或依赖项注入)
  4. 我希望我的集成测试可以扩展该 Magento\TestFramework\TestCase\AbstractController测试,所以我的助手与Magento测试相同
  5. 我希望能够独立于测试套件的其余部分运行测试(即不必等待2个小时即可运行15秒钟的测试)
  6. 我想将测试与Magento的测试分开存储

开发文档站点上有一些关于测试的入门文章,但它们似乎是针对运行Magento附带的测试,而不是创建和运行自己的测试。这里有旧的示例模块,但是它们都扩展了PHPUnit_Framework_TestCase类并且似乎是单元测试(即,不依赖Magento框架的测试代码)

有Magento提供的方法吗?

如果不是,那么是否有人以Magento开发人员社区的测试可以将其作为标准的方式来滚动自己的设置?

Answers:


20

这对我们有效,但我们尚未考虑将其移至另一个地址以解决6。)

1.)将您的集成测试置于dev/tests/integration/testsuite/Vendor
2.)dev/tests/integration/phpunit.dist.xml

dev/tests/integration/phpunit.xml

并更换

        <directory suffix="Test.php">testsuite</directory>
        <directory suffix="Test.php">../../../update/dev/tests/integration/testsuite</directory>
        <exclude>testsuite/Magento/Test/Integrity</exclude>
        <exclude>testsuite/Magento/MemoryUsageTest.php</exclude>

        <directory suffix="Test.php">testsuite/Vendor</directory>

3.)运行它../../../vendor/bin/phpunit../../../vendor/bin/phpunit path/to/tests从dev / test / integration文件夹运行

请注意,至少在首次运行时,集成测试会花费15秒以上的时间,因为它实际上已安装了Magento。如果使用,您可以节省以后的运行

<const name="TESTS_CLEANUP" value="disabled"/>

在你的 phpunit.xml


11

我已经成功地将集成测试放置在一个单独的目录中:src/My/Module/test/integration。它也可以是其他任何目录,例如app/code/My/Module/Test

将它们作为新的测试套件添加到Magento集成测试中:复制dev/tests/integration/phpunit.xml.distdev/tests/integration/phpunit.xml并在<testsuites>节点中添加以下内容:

<testsuite name="My_Module">
    <directory suffix="Test.php">../../../src/My/Module/test</directory>
</testsuite>

然后从dev/tests/integration目录运行以下测试:

../../../vendor/bin/phpunit --testsuite "My_Module"

使用该--testsuite参数,您可以按名称选择一个测试套件,这样就不会一次运行所有集成测试。

更新:灯具

要使用自己的灯具,需要一些解决方法,因为在Magento\TestFramework\Annotation灯具的基本目录中是全局定义的。但是幸运的是,Magento也允许将方法名称用作固定装置,因此可以进行以下工作:

/**
 * @magentoDataFixture loadFixture
 */
public function testSomething()
{
}

public static function loadFixture()
{
    include __DIR__ . '_files/something_fixture.php';
}

1
在这里使用@magentoDataFixture github.com/magento/magento2/blob/develop/dev/tests/integration/时,您是否会遇到问题特别是与模块中的自定义夹具与核心夹具结合使用时?
克里斯托夫在Fooman'3

1
我还没有尝试过,但是看起来像是一个问题。可能需要设置包含路径以使这些灯具起作用。
Fabian Schmengler,

1
@KristofatFooman找到了灯具的解决方案,请参阅更新
Fabian Schmengler 2016年

很好的解决方案。这里可能存在一些缺陷。首先,有一个错字- __DIR__后面应跟一个斜线(/_files)。其次,从TestFramework内部加载灯具,以便__DIR__实际指向TestFramework目录,而不是您自己的模块。的ComponentRegistrar:可用于本require $ObjectManager::getInstance()->get(ComponentRegistrar::class)->getPath('module', 'Foo_Bar').'/Test/Integration/_files/example.php';
Jisse Reitsma

10

我在集成测试中做了一些工作,这是我到目前为止发现的。

基本上,我遵循了与Fooman所说的相似的步骤,但有一些区别,以便使集成测试成为我模块的一部分。

这些是我遵循的步骤:

1-将您的集成测试放在 app/code/Vendor/CustomModule/Test/Integration

2-复制dev/tests/integration/phpunit.dist.xmldev/tests/integration/phpunit.xml

并更换

<testsuite name="Magento Integration Tests">
    <directory suffix="Test.php">testsuite</directory>
    <directory suffix="Test.php">../../../update/dev/tests/integration/testsuite</directory>
    <exclude>testsuite/Magento/Test/Integrity</exclude>
    <exclude>testsuite/Magento/MemoryUsageTest.php</exclude>
</testsuite>

<testsuite name="Magento Integration Tests">
    <directory suffix="Test.php">../../../app/code/Vendor/CustomModule/Test/Integration</directory>
</testsuite>

3-然后我使用CLI工具运行它 bin/magento dev:test:run integration

您应该牢记Fooman关于“ TESTS_CLEANUP”的说法,以及如果启用了清除功能,则需要设置集成测试所需的时间。

在这里,我添加了一个功能示例以供进一步参考。您将看到如何访问对象管理器,如何生成Magento类的实例以及如何使用Magento固定装置。

应用/代码/供应商/ CustomModule /控制器/Order/Info.php

namespace Vendor\CustomModule\Controller\Order;

use Magento\Framework\Controller\ResultFactory;

class Info
    extends \Magento\Framework\App\Action\Action
{
    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
    )
    {
        $this->orderRepository = $orderRepository;
        parent::__construct($context);
    }

    /**
     * Return Json OrderInfo
     *
     * @return \Magento\Framework\Controller\Result\Json $this
     */
    public function execute()
    {
        $orderId = $this->getRequest()->getParam('id');
        $order = $this->orderRepository->get($orderId);
        $orderInfo = [
            'total' => $order->getBaseGrandTotal()
        ];

        /** @var \Magento\Framework\Controller\Result\Json $result */
        $result = $this->resultFactory->create(ResultFactory::TYPE_JSON);
        return $result->setData($orderInfo);
    }

}

app / code / Vendor / CustomModule / etc / frontend / routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="vendor_custommodule" frontName="vendor_custommodule">
            <module name="Vendor_CustomModule"/>
        </route>
    </router>
</config>

app / code / Vendor / CustomModule / etc / module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_CustomModule" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Sales" />
        </sequence>
    </module>
</config>

应用/代码/供应商/ CustomModule /测试/集成/控制器/订单/InfoTest.php

namespace Vendor\CustomModule\Controller\Order;

use Magento\TestFramework\TestCase\AbstractController;

class InfoTest extends AbstractController
{
    public function getOrderInfoActionDataProvider()
    {
        return [
            'order with one simple item' => [
                'incrementId' => '100000001',
                'contentType' => 'application/json',
                'orderTotal' => 100
            ]
        ];
    }

    /**
     * @dataProvider getOrderInfoActionDataProvider
     * @magentoDataFixture Magento/Sales/_files/order.php
     */
    public function testOrderInfoAction($incrementId, $expectedContentType, $expectedOrderTotal)
    {
        /** @var $objectManager \Magento\TestFramework\ObjectManager */
        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();

        /** @var \Magento\Sales\Model\OrderFactory $orderFactory */
        $orderFactory = $objectManager->get('Magento\Sales\Model\OrderFactory');
        $order = $orderFactory->create();
        $order->loadByIncrementId($incrementId);

        $this->dispatch("vendor_custommodule/order/info/id/{$order->getId()}");

        $contentType = $this->getResponse()->getHeader('Content-Type');
        $this->assertEquals($expectedContentType, $contentType->getFieldValue());

        $responseJson = $this->getResponse()->getBody();
        $responseArray = json_decode($responseJson, true);
        $this->assertEquals($expectedOrderTotal, $responseArray['total']);
    }
}

应用/代码/供应商/CustomModule/registration.php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_CustomModule',
    __DIR__
);

请注意,只要您使用Magento磁芯的固定装置,您自己的解决方案就可以正常工作。如果要使用自己的固定装置,则会遇到前面讨论的问题。
Jisse Reitsma
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.