Creazione di test di integrazione per i moduli Magento 2


27

Finora per le mie esigenze di test di Magento 2, ho usato PHP Unit come (più o meno) un tester di accettazione - testando i risultati delle richieste del server e HTML fatte in un sistema con i miei moduli installati. Mi piacerebbe essere in grado di creare i miei test di integrazione. Gli strumenti di test forniti con Magento 2 consentono agli sviluppatori di terze parti di creare i propri test di integrazione che sfruttano il codice del framework di test di Magento? O lanceremo tutti il ​​nostro bootstrap?

Questo è

  1. Sono uno sviluppatore di Magento
  2. Vorrei creare un test di integrazione
  3. Avrei il mio test di integrazione per avere un ambiente Magento completamente bootstrap in cui giocare (cioè gestore degli oggetti e / o iniezione di dipendenza da usare)
  4. Vorrei che il mio test di integrazione estendesse il Magento\TestFramework\TestCase\AbstractControllertest in modo da avere gli stessi aiutanti dei test Magento
  5. Mi piacerebbe essere in grado di eseguire i miei test in modo isolato dal resto della suite di test (cioè non dover aspettare 2 ore per eseguire i miei 15 secondi di test)
  6. Vorrei che i miei test fossero archiviati separatamente dai test di Magento

Il sito dev docs contiene alcuni articoli di base sui test, ma sembrano orientati all'esecuzione dei test forniti con Magento e non alla creazione e all'esecuzione dei propri test. Ci sono i vecchi moduli di esempio , ma tutti estendono la PHPUnit_Framework_TestCaseclasse e sembrano essere test unitari (ovvero test del codice che non si basa sul framework Magento)

Esiste un modo Magento per farlo?

In caso contrario, qualcuno ha modificato la propria configurazione in modo tale che il test della comunità di sviluppatori Magento possa adottarla come standard?

Risposte:


20

Questo funziona per noi, ma non abbiamo ancora cercato di spostarli in una posizione separata all'indirizzo 6.)

1.) Collocare i test di integrazione in dev/tests/integration/testsuite/Vendor
2.) copia dev/tests/integration/phpunit.dist.xml
in
dev/tests/integration/phpunit.xml

e sostituisci

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

con

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

3.) eseguirlo ../../../vendor/bin/phpunito con ../../../vendor/bin/phpunit path/to/testsdalla cartella dev / test / integration

Si noti che i test di integrazione impiegano più di 15 secondi, almeno alla prima esecuzione poiché installa essenzialmente Magento. È possibile salvare sulle esecuzioni successive se si utilizza

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

nel tuo phpunit.xml


11

Ho messo con successo i miei test di integrazione in una directory separata: src/My/Module/test/integration. Potrebbe essere qualsiasi altra directory, come app/code/My/Module/Test.

Aggiungerli come nuova suite di test per i test di integrazione Magento: copia dev/tests/integration/phpunit.xml.distper dev/tests/integration/phpunit.xmle aggiungere la seguente nel <testsuites>nodo:

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

Quindi eseguire i test in questo modo dalla dev/tests/integrationdirectory:

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

Con il --testsuiteparametro è possibile selezionare una suite di test per nome, in modo che non tutti i test di integrazione vengano eseguiti contemporaneamente

Aggiornamento: partite

Per usare le proprie fixture, era necessaria una piccola soluzione, perché nella Magento\TestFramework\Annotationdirectory base delle fixture è definita a livello globale. Ma per fortuna Magento consente anche i nomi dei metodi come dispositivi, quindi i seguenti lavori:

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

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

1
Non incontreresti problemi quando usi @magentoDataFixture qui github.com/magento/magento2/blob/develop/dev/tests/integration/… specialmente quando combini con un dispositivo personalizzato del tuo modulo con uno principale?
Kristof a Fooman l'

1
tbh non l'ho ancora provato ma sembra un problema, sì. Potrebbe essere necessario impostare il percorso di inclusione per far funzionare questi dispositivi.
Fabian Schmengler

1
@KristofatFooman Trovato una soluzione per gli infissi, vedi aggiornamento
Fabian Schmengler

Ottima soluzione Potrebbero esserci un paio di difetti qui. Prima di tutto, c'è un refuso - il __DIR__dovrebbe essere seguito da una barra ( /_files). In secondo luogo, l'apparecchiatura viene caricata dall'interno di TestFramework in modo che __DIR__punti effettivamente alla directory TestFramework e non al proprio modulo. Il ComponentRegistrarpuò essere usato per questo:require $ObjectManager::getInstance()->get(ComponentRegistrar::class)->getPath('module', 'Foo_Bar').'/Test/Integration/_files/example.php';
Jisse Reitsma il

10

Ho giocato un po 'con i test di integrazione, e questo è quello che ho trovato finora.

Fondamentalmente, ho seguito passaggi simili a quanto affermato da Fooman, con alcune differenze per rendere il test di integrazione parte del mio modulo.

Questi sono i passaggi che ho seguito:

1- Collocare i test di integrazione sotto app/code/Vendor/CustomModule/Test/Integration

2- Copia dev/tests/integration/phpunit.dist.xmlindev/tests/integration/phpunit.xml

e sostituisci

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

con

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

3- Quindi lo eseguo usando lo strumento CLI bin/magento dev:test:run integration

Dovresti tenere presente cosa dice Fooman in merito a "TESTS_CLEANUP" e il tempo necessario per impostare i test di integrazione se hai l'abilitazione per la pulizia.

Qui aggiungo un esempio funzionale per ulteriori riferimenti. Vedrai come accedere al gestore oggetti e generare istanze di classi Magento, oltre a utilizzare i dispositivi Magento.

app / code / Venditore / CustomModule / Controller / ordine / 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 / Venditore / 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 / Venditore / 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 / Venditore / CustomModule / Test / integrazione / Controller / ordine / 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 / Venditore / CustomModule / registration.php

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

Si noti che la propria soluzione va bene e funziona, purché si utilizzino gli apparecchi del core Magento. Se vuoi usare i tuoi dispositivi, ti imbatterai nei problemi come discusso in precedenza.
Jisse Reitsma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.