Criando testes de integração para módulos Magento 2

27

Até agora, para minhas necessidades de teste do Magento 2, eu tenho usado o PHP Unit como (mais ou menos) um testador de aceitação - testando resultados de solicitações de servidor e HTML feitas em um sistema com meus módulos instalados. Eu gostaria de poder criar meus próprios testes de integração. As ferramentas de teste fornecidas com o Magento 2 permitem que desenvolvedores terceiros criem seus próprios testes de integração que aproveitam o código da estrutura de testes do Magento? Ou estaremos todos lançando nossa própria inicialização?

Isso é

  1. Sou desenvolvedor Magento
  2. Eu gostaria de criar um teste de integração
  3. Eu faria meu teste de integração para ter um ambiente Magento totalmente de inicialização (por exemplo, gerenciador de objetos e / ou injeção de dependência para usar)
  4. Gostaria que meu teste de integração estendesse o Magento\TestFramework\TestCase\AbstractControllerteste, para que eu tenha os mesmos auxiliares que os testes Magento
  5. Eu gostaria de poder executar meus testes isoladamente do restante do conjunto de testes (ou seja, não tenho que esperar 2 horas para executar meus 15 segundos de testes)
  6. Gostaria que meus testes fossem armazenados separadamente dos testes do Magento

O site dev docs possui alguns artigos iniciais sobre testes, mas eles parecem orientados para executar os testes que acompanham o Magento e não para criar e executar seus próprios testes. Existem os módulos de amostra antigos , mas todos eles estendem a PHPUnit_Framework_TestCaseclasse e parecem ser testes de unidade (ou seja, código de teste que não depende da estrutura do Magento)

Existe uma maneira fornecida do Magento de fazer isso?

Caso contrário, alguém criou sua própria configuração de forma que o teste da comunidade de desenvolvedores Magento pudesse adotá-la como padrão?

Alan Storm
fonte

Respostas:

20

Isso funciona para nós, mas ainda não analisamos como movê-los para um local separado para o endereço 6.)

1.) Coloque seus testes de integração em dev/tests/integration/testsuite/Vendor
2.) copie dev/tests/integration/phpunit.dist.xml
para
dev/tests/integration/phpunit.xml

e substitua

        <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>

com

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

3.) execute-o ../../../vendor/bin/phpunitou com a ../../../vendor/bin/phpunit path/to/testspartir da pasta dev / test / integration

Observe que os testes de integração levam mais de 15 segundos, pelo menos na primeira execução, pois essencialmente instala o Magento. Você pode salvar em execuções subsequentes se usar

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

na tua phpunit.xml

Kristof na Fooman
fonte
11

Eu coloquei com sucesso meus testes de integração em um diretório separado: src/My/Module/test/integration. Poderia ser qualquer outro diretório também, como app/code/My/Module/Test.

Adicioná-los como nova suíte de teste para os testes de integração Magento: Copiar dev/tests/integration/phpunit.xml.distpara dev/tests/integration/phpunit.xmle adicione a seguinte no <testsuites>nó:

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

Em seguida, execute os testes como este no dev/tests/integrationdiretório:

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

Com o --testsuiteparâmetro, você pode selecionar um conjunto de testes por nome, para que nem todos os testes de integração sejam executados ao mesmo tempo

Atualização: Luminárias

Para usar equipamentos próprios, foi necessária uma pequena solução alternativa, porque no Magento\TestFramework\Annotationdiretório base do equipamento é definido globalmente. Mas, felizmente, o Magento também permite nomes de métodos como acessórios, portanto, o seguinte funciona:

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

public static function loadFixture()
{
    include __DIR__ . '_files/something_fixture.php';
}
Fabian Schmengler
fonte
11
Você não teria problemas ao usar o @magentoDataFixture aqui github.com/magento/magento2/blob/develop/dev/tests/integration/… especialmente ao combinar com um acessório personalizado do seu módulo com um acessório principal?
Kristof em Fooman 31 /
11
Ainda não tentei, mas parece um problema, sim. Pode ser necessário definir o caminho de inclusão para que esses equipamentos funcionem.
Fabian Schmengler 8/03/16
11
@KristofatFooman encontrado uma solução para as luminárias, veja update
Fabian Schmengler
Great solution. There might be a couple of flaws here. First of all, there is a typo - the __DIR__ should be followed by a slash (/_files). Second, the fixture is loaded from within the TestFramework so that the __DIR__ actually points to the TestFramework directory and not your own module. The ComponentRegistrar can be used for this: require $ObjectManager::getInstance()->get(ComponentRegistrar::class)->getPath('module', 'Foo_Bar').'/Test/Integration/_files/example.php';
Jisse Reitsma
10

Eu brinquei um pouco com os testes de integração, e foi isso que encontrei até agora.

Basicamente, segui etapas semelhantes ao que Fooman disse, com algumas diferenças para fazer o teste de integração fazer parte do meu módulo.

Estes são os passos que segui:

1- Coloque seus testes de integração em app/code/Vendor/CustomModule/Test/Integration

2- Copiar dev/tests/integration/phpunit.dist.xmlparadev/tests/integration/phpunit.xml

e substitua

<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>

com

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

3- Então eu o executo usando a ferramenta CLI bin/magento dev:test:run integration

Você deve ter em mente o que Fooman diz sobre o "TESTS_CLEANUP" e o tempo necessário para configurar os testes de integração, se a limpeza estiver ativada.

Aqui eu adiciono um exemplo funcional para referência adicional. Você verá como pode acessar o gerenciador de objetos e gerar instâncias das classes Magento, além de usar equipamentos Magento.

app / code / Vendor / CustomModule / Controller / 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>

app / code / Vendor / CustomModule / Test / Integration / Controller / Order / 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']);
    }
}

app / code / Vendor / CustomModule / registration.php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_CustomModule',
    __DIR__
);
Facundo Capua
fonte
Observe que sua própria solução é boa e funciona, desde que você esteja usando os equipamentos do núcleo Magento. Se você quiser usar seus próprios equipamentos, encontrará os problemas conforme discutido anteriormente.
Jisse Reitsma 16/07