Membuat Tes Integrasi untuk Modul Magento 2

27

Sejauh ini untuk kebutuhan pengujian Magento 2 saya, saya telah menggunakan Unit PHP sebagai (kurang lebih) penguji penerimaan - hasil pengujian server dan permintaan HTML yang dibuat menjadi sistem dengan modul saya terinstal. Saya ingin dapat membuat tes integrasi saya sendiri. Apakah alat pengujian yang dikirimkan bersama Magento 2 memungkinkan pengembang pihak ketiga untuk membuat tes integrasi mereka sendiri yang memanfaatkan kode kerangka uji Magento? Atau apakah kita semua akan menggulung bootstrap kita sendiri?

Itu adalah

  1. Saya adalah pengembang Magento
  2. Saya ingin membuat tes integrasi
  3. Saya ingin tes integrasi saya untuk memiliki lingkungan Magento yang sepenuhnya bootstrap untuk dimainkan (yaitu manajer objek dan / atau injeksi ketergantungan untuk digunakan)
  4. Saya ingin tes integrasi saya memperpanjang Magento\TestFramework\TestCase\AbstractControllertes jadi saya memiliki pembantu yang sama dengan tes Magento
  5. Saya ingin dapat menjalankan tes secara terpisah dari sisa test suite (yaitu tidak harus menunggu 2 jam untuk menjalankan tes 15 detik saya)
  6. Saya ingin tes saya disimpan secara terpisah dari tes Magento

Situs dev docs memiliki beberapa artikel pemula tentang pengujian, tetapi mereka tampaknya berorientasi menjalankan tes yang dikirimkan bersama Magento dan tidak membuat dan menjalankan tes Anda sendiri. Ada modul sampel lama , tetapi semuanya memperluas PHPUnit_Framework_TestCasekelas dan tampaknya merupakan unit test (yaitu kode pengujian yang tidak bergantung pada kerangka kerja Magento)

Apakah ada cara yang disediakan Magento untuk melakukan ini?

Jika tidak, adakah orang yang memasang pengaturan mereka sendiri sedemikian rupa sehingga pengujian komunitas pengembang Magento dapat mengadopsinya sebagai standar?

Alan Storm
sumber

Jawaban:

20

Ini berfungsi untuk kami, tetapi kami belum melihat untuk memindahkan mereka ke lokasi terpisah untuk alamat 6.)

1.) Tempatkan uji integrasi Anda di bawah dev/tests/integration/testsuite/Vendor
2.) salin dev/tests/integration/phpunit.dist.xml
ke
dev/tests/integration/phpunit.xml

dan ganti

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

dengan

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

3.) jalankan ../../../vendor/bin/phpunitatau dengan ../../../vendor/bin/phpunit path/to/testsdari folder dev / test / integrasi

Harap dicatat bahwa tes integrasi membutuhkan waktu lebih dari 15 detik, setidaknya saat dijalankan pertama karena pada dasarnya menginstal Magento. Anda dapat menyimpan pada menjalankan selanjutnya jika Anda menggunakan

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

di Anda phpunit.xml

Kristof di Fooman
sumber
11

Saya telah berhasil ditempatkan tes integrasi saya ke direktori terpisah: src/My/Module/test/integration. Bisa juga direktori lain, seperti app/code/My/Module/Test.

Tambahkan mereka sebagai rangkaian uji baru ke tes integrasi Magento: Salin dev/tests/integration/phpunit.xml.distke dev/tests/integration/phpunit.xmldan tambahkan berikut ini di <testsuites>simpul:

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

Kemudian jalankan tes seperti ini dari dev/tests/integrationdirektori:

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

Dengan --testsuiteparameter, Anda dapat memilih satu test suite berdasarkan nama, sehingga tidak semua tes integrasi dijalankan sekaligus

Perbarui: Jadwal

Untuk menggunakan perlengkapan sendiri, sedikit solusi diperlukan, karena dalam Magento\TestFramework\Annotationdirektori dasar fixture didefinisikan secara global. Tapi untungnya Magento memungkinkan nama metode sebagai perlengkapan juga, jadi berikut ini berfungsi:

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

public static function loadFixture()
{
    include __DIR__ . '_files/something_fixture.php';
}
Fabian Schmengler
sumber
1
Tidakkah Anda akan mendapat masalah ketika menggunakan @magentoDataFixture di sini github.com/magento/magento2/blob/develop/dev/tests/integration/... terutama saat menggabungkan dengan perlengkapan khusus dari modul Anda dengan modul inti?
Kristof di Fooman
1
tbh saya belum mencobanya tapi sepertinya masalah, ya. Mungkin perlu untuk mengatur jalur sertakan agar perlengkapan ini berfungsi.
Fabian Schmengler
1
@KristofatFooman Menemukan solusi untuk pertandingan ini, lihat pembaruan
Fabian Schmengler
Solusi bagus Mungkin ada beberapa kekurangan di sini. Pertama-tama, ada kesalahan ketik - yang __DIR__harus diikuti dengan garis miring ( /_files). Kedua, fixture dimuat dari dalam TestFramework sehingga __DIR__sebenarnya menunjuk ke direktori TestFramework dan bukan modul Anda sendiri. The ComponentRegistrardapat digunakan untuk ini:require $ObjectManager::getInstance()->get(ComponentRegistrar::class)->getPath('module', 'Foo_Bar').'/Test/Integration/_files/example.php';
Jisse Reitsma
10

Saya telah bermain sedikit dengan tes integrasi, dan inilah yang saya temukan sejauh ini.

Pada dasarnya, saya telah mengikuti langkah-langkah serupa dengan apa yang dikatakan Fooman, dengan beberapa perbedaan untuk menjadikan tes integrasi menjadi bagian dari modul saya.

Ini adalah langkah-langkah yang saya ikuti:

1- Tempatkan tes integrasi Anda di bawah app/code/Vendor/CustomModule/Test/Integration

2- Salin dev/tests/integration/phpunit.dist.xmlkedev/tests/integration/phpunit.xml

dan ganti

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

dengan

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

3 - Kemudian saya menjalankannya menggunakan alat CLI bin/magento dev:test:run integration

Anda harus mengingat apa yang dikatakan Fooman tentang "TESTS_CLEANUP" dan waktu yang diperlukan untuk menyiapkan tes integrasi jika Anda mengaktifkan pembersihan.

Di sini saya menambahkan contoh fungsional untuk referensi lebih lanjut. Anda akan melihat bagaimana Anda dapat mengakses manajer objek, dan membuat instance kelas Magento, serta menggunakan perlengkapan 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
sumber
Harap dicatat bahwa solusi Anda sendiri baik-baik saja dan berfungsi, selama Anda menggunakan perlengkapan inti Magento. Jika Anda ingin menggunakan perlengkapan Anda sendiri, Anda akan menemukan masalah seperti yang dibahas sebelumnya.
Jisse Reitsma