Tworzenie testów integracji dla modułów Magento 2

27

Do tej pory dla moich potrzeb testowania Magento 2 używałem PHP Unit jako (mniej więcej) testera akceptacji - testującego wyniki żądań serwera i HTML wprowadzonych do systemu z zainstalowanymi moimi modułami. Chciałbym móc tworzyć własne testy integracyjne. Czy narzędzia testowe dostarczane z Magento 2 pozwalają programistom zewnętrznym tworzyć własne testy integracyjne wykorzystujące kodowy szkielet testowy Magento? A może wszyscy będziemy tworzyć własny pasek startowy?

To jest

  1. Jestem programistą Magento
  2. Chciałbym utworzyć test integracyjny
  3. Chciałbym, aby mój test integracyjny miał środowisko Magento w pełni uruchamiające się (np. Menedżer obiektów i / lub zastrzyk zależności do użycia)
  4. Chciałbym, aby mój test integracyjny przedłużył Magento\TestFramework\TestCase\AbstractControllertest, więc mam tych samych pomocników, co testy Magento
  5. Chciałbym móc uruchomić moje testy w oderwaniu od reszty zestawu testów (tj. Nie muszę czekać 2 godziny na uruchomienie moich 15 sekund testów)
  6. Chciałbym, aby moje testy były przechowywane oddzielnie od testów Magento

Witryna Dev Docs zawiera kilka artykułów startowych na temat testowania, ale wydają się one zorientowane na przeprowadzanie testów dostarczanych z Magento, a nie na tworzenie i uruchamianie własnych testów. Istnieją stare przykładowe moduły , ale wszystkie rozszerzają PHPUnit_Framework_TestCaseklasę i wydają się być testami jednostkowymi (tj. Testowaniem kodu, który nie opiera się na frameworku Magento)

Czy istnieje sposób na to, aby zapewnić Magento?

Jeśli nie, to czy ktoś wypuścił własną konfigurację w taki sposób, że test społeczności programistów Magento mógłby ją przyjąć jako standard?

Alan Storm
źródło

Odpowiedzi:

20

Działa to dla nas, ale nie zastanawialiśmy się jeszcze nad przeniesieniem ich w osobne miejsce pod adresem 6.)

1.) Umieść swoje testy integracyjne pod dev/tests/integration/testsuite/Vendor
2.) skopiuj dev/tests/integration/phpunit.dist.xml
do
dev/tests/integration/phpunit.xml

i zamień

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

z

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

3.) uruchom go ../../../vendor/bin/phpunitlub z ../../../vendor/bin/phpunit path/to/testspoziomu folderu dev / test / integracji

Należy pamiętać, że testy integracyjne trwają dłużej niż 15 sekund, przynajmniej przy pierwszym uruchomieniu, ponieważ zasadniczo instaluje Magento. Możesz zaoszczędzić na kolejnych uruchomieniach, jeśli używasz

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

w Twoim phpunit.xml

Kristof w Fooman
źródło
11

Mam powodzeniem umieszczony moich testów integracyjnych w osobnym katalogu: src/My/Module/test/integration. Może to być również dowolny inny katalog app/code/My/Module/Test.

Dodaj je jako nowy test pakietu do testów integracyjnych Magento: Kopiuj dev/tests/integration/phpunit.xml.distdo dev/tests/integration/phpunit.xmli dodaj następujący w <testsuites>węźle:

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

Następnie uruchom takie testy z dev/tests/integrationkatalogu:

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

Za pomocą tego --testsuiteparametru można wybrać jeden zestaw testów według nazwy, aby nie wszystkie testy integracyjne były uruchamiane jednocześnie

Aktualizacja: Urządzenia

Aby użyć własnych urządzeń, konieczne było obejście tego problemu, ponieważ w Magento\TestFramework\Annotationkatalogu podstawowym urządzenia jest zdefiniowany globalnie. Ale na szczęście Magento zezwala również na nazwy metod jako urządzenia, więc następujące działania:

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

public static function loadFixture()
{
    include __DIR__ . '_files/something_fixture.php';
}
Fabian Schmengler
źródło
1
Czy nie napotkalibyście problemów podczas korzystania z @magentoDataFixture tutaj github.com/magento/magento2/blob/develop/dev/tests/integration/…, szczególnie w połączeniu z niestandardowym urządzeniem z modułu z rdzeniem?
Kristof w Fooman
1
Nie próbowałem jeszcze, ale wygląda na to, że to problem. Może być konieczne ustawienie ścieżki dołączania, aby te urządzenia działały.
Fabian Schmengler
1
@KristofatFooman Znaleziono rozwiązanie dla urządzeń, patrz aktualizacja
Fabian Schmengler
Świetne rozwiązanie. Może tu być kilka wad. Przede wszystkim jest literówka - po niej __DIR__należy wstawić ukośnik ( /_files). Po drugie, urządzenie jest ładowane z poziomu TestFramework, tak że __DIR__faktycznie wskazuje na katalog TestFramework, a nie na własny moduł. ComponentRegistrarMogą być wykorzystane do tego:require $ObjectManager::getInstance()->get(ComponentRegistrar::class)->getPath('module', 'Foo_Bar').'/Test/Integration/_files/example.php';
Jisse Reitsma
10

Grałem trochę w testy integracyjne i to właśnie znalazłem do tej pory.

Zasadniczo wykonałem podobne kroki, co powiedział Fooman, z pewnymi różnicami, aby test integracyjny był częścią mojego modułu.

Oto kroki, które wykonałem:

1- Umieść testy integracji pod app/code/Vendor/CustomModule/Test/Integration

2- Kopiuj dev/tests/integration/phpunit.dist.xmldodev/tests/integration/phpunit.xml

i zamień

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

z

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

3- Następnie uruchamiam go za pomocą narzędzia CLI bin/magento dev:test:run integration

Powinieneś pamiętać o tym, co Fooman mówi o „TESTS_CLEANUP” oraz o czasie potrzebnym do skonfigurowania testów integracji, jeśli masz włączone czyszczenie.

Tutaj dodaję funkcjonalny przykład w celu uzyskania dalszych informacji. Zobaczysz, jak możesz uzyskać dostęp do menedżera obiektów i wygenerować instancję klas Magento, a także korzystać z urządzeń 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 / tras.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 / register.php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_CustomModule',
    __DIR__
);
Facundo Capua
źródło
Pamiętaj, że twoje własne rozwiązanie jest w porządku i działa, o ile korzystasz z urządzeń rdzenia Magento. Jeśli chcesz korzystać z własnych urządzeń, wpadniesz na problemy, jak omówiono wcześniej.
Jisse Reitsma