Magento 2'de PHPUnit 4.1 ile PHP7 kodunu test etmek için doğru yöntem nedir?


23

Modüllerimi yazarken, onlara uygulamanın en kritik kısımları için birim testleri sağlamaya çalışıyorum. Bununla birlikte, şu anda (Magento 2.1.3) birim testleri yazmanın birkaç yolu vardır:

Testin farklı yolları

  • Entegre edin bin/magento dev:tests:run unitve Magento ile birlikte gelen varsayılan phpunit ayarlarının üzerinde çalıştırın.
  • Ayrı olarak yaz, çalıştır vendor/bin/phpunit app/code/Vendor/Module/Test/Unitve Magento olan herşeyle alay et.
  • Onları ayrı ayrı yaz, her şeyle alay et ve PHPUnit'in sistem global versiyonunu kullan.
  • Bunları ayrı yazınız, çalıştırınız vendor/bin/phpunitfakat yine de faydalanınız \Magento\Framework\TestFramework\Unit\Helper\ObjectManager.

Magento 2 ve PHP Birimi

Bunun yanı sıra, Magento 2, PHP7 uyumlu olmayan PHPUnit 4.1.0 ile birlikte gelir. Yazım kurallarına göre yerliler (like stringand `int) ve imzalarınızda dönüş türlerinin bildirilmesi hatalar verecektir. Örneğin, bunun gibi bir yöntem imzasına sahip bir arayüz / sınıf:

public function foo(string $bar) : bool;

... PHPUnit 4.1.0 ile alay edilemez. :-(

Şu anki durumum

Bu yüzden şu anda çoğunlukla ünite testlerimi üçüncü şekilde yazıyorum (sistem-global PHPUnit versiyonunu arayarak).

Kurulumumda, dünya çapında PHPUnit 5.6 yüklüyüm, bu yüzden uygun PHP7 kodunu yazabilirim, ancak bazı değişiklikler yapmalıyım. Örneğin:

phpunit.xml Besteci otomatik yükleyiciden faydalanabilmem için şöyle görünmesi gerekiyor:

<?xml version="1.0"?>
<phpunit bootstrap="../../../../../../vendor/autoload.php"
         colors="true">
    <testsuites>
        <testsuite name="Testsuite">
            <directory>.</directory>
        </testsuite>
    </testsuites>
</phpunit>

... ve tüm setUp()-metodlarımda, aşağıdaki onaylara sahibim, böylece testlerimi ileriye dönük uyumlulukla yazabilirim:

// Only allow PHPUnit 5.x:
if (version_compare(\PHPUnit_Runner_Version::id(), '5', '<')) {
    $this->markTestSkipped();
}

Bu sayede testlerim Magentos'un yerleşik PHPUnit'i tarafından yapıldığında hata yapmaz.

Benim sorum

İşte benim sorum: bu birim testi yazmanın 'sağlıklı' bir yolu mu? Çünkü Magento'nun test etmenize yardımcı olacak bir sürü araçla birlikte geldiği doğru gözükmüyor ve bunları kullanamıyorum çünkü PHP7 kullanıyorum. GitHub'da bu sorunu çözen biletler olduğunu biliyorum, ancak topluluğun şu anda testleri nasıl yazdığını merak ediyorum.

Magento 2'de birim testleri yazmanın bir yolu var, bu yüzden kodumu 'düşürmem' gerekmiyor ve yine de Magentos'un yerleşik yardımcılarını nesne yöneticisinin dokunduğu her şeyi alay etmek için kullanabilir miyim? Yoksa birim testlerinde bile nesne yöneticisini kullanmak kötü bir uygulama mı?

Kendi özel modüllerinizi nasıl test edeceğinize dair doğru yolun ne olduğuna dair birçok rehberlik / örnek eksik.


1
Ne güzel bir soru.
camdixon

Yanıtlar:


17

Birlikte verilen PHPUnit sürümünü kullanmak, eski olsa bile, muhtemelen CI sırasında tüm modüller için testlerin yapılmasına izin verecek en iyi yoldur.

Testleri, birlikte verilen test çerçevesiyle uyumlu olmayan bir şekilde yazmak, testlerin değerini büyük ölçüde azaltıyor.
Elbette CI'yi testlerinizi PHPUnit'in farklı bir versiyonuyla çalıştırmak için ayarlayabilirsiniz, ancak bu derleme sistemine çok fazla karmaşıklık katar.

Bununla birlikte, PHP 5.6'yı desteklemeye değmeyeceği konusunda size katılıyorum. PHP7 skaler tip ipucu ve dönüş tipi ipuçlarını mümkün olduğunca kullanıyorum (artı, pazar yeri umrumda değil).

PHPUnit 4.1 alaycı kütüphanesinin sınırlamalarını aşmak için, geçmişte kullandığım en az iki oldukça basit geçici çözüm vardır:

  1. Örneğin, test çiftlerinizi oluşturmak için adsız veya normal sınıflar kullanın

    $fooIsFalseStub = new class extends Foo implements BarInterface() {
        public function __construct(){};
        public function isSomethingTrue(string $something): bool
        {
            return false;
        }
    };
  2. Birlikte verilen PHPUnit'i kullanın, ancak besteci aracılığıyla eklenebilecek üçüncü taraf alaycı bir kitaplık kullanın, require-devörneğin https://github.com/padraic/mockery . Çalıştığım tüm alaycı kütüphaneler, 4.1 gibi PHP'nin çok eski bir sürümü olsa bile, herhangi bir test çerçevesi ile kolayca kullanılabilir.

Bunların hiçbirinin diğerine göre teknik üstünlüğü yoktur. İstediğiniz herhangi bir test çift mantığını da uygulayabilirsiniz.

Şahsen ben anonim sınıfları kullanmayı tercih ederim, çünkü bu harici bağımlılıkların sayısını arttırmaz ve bu şekilde yazmak daha eğlencelidir.

EDIT :
Sorularınızı cevaplamak için:

Mockery, PHPUnit 4.1.0'ın PHP7 tipi ipuçlarını doğru şekilde kullanamama sorununu 'çözüyor mu?'

Evet, aşağıdaki örneğe bakın.

Ve anonim sınıfların alay etmenin faydaları nelerdir?

Test çiftleri oluşturmak için anonim sınıfları kullanmak da "alaycı" dır, PHPUnits veya Mockery veya benzeri bir alaycı kitaplık kullanmaktan gerçekten farklı değildir.
Bir sahte, nasıl yaratıldığına bakılmaksızın sadece belirli bir test tipi üzerindedir .
Anonim sınıflar veya alaycı bir kütüphane kullanma arasındaki küçük bir fark, anonim sınıfların harici bir kütüphane bağımlılığına sahip olmamasıdır, çünkü sadece düz PHP'dir. Aksi halde, fayda veya sakınca yoktur. Bu sadece bir tercih meselesi. Testin herhangi bir test çerçevesi veya alaycı kitaplık ile ilgili olmadığını gösterdiğinden, test sadece sistemi test eden ve otomatik olarak çalıştığını doğrulayan bir kod yazdığını gösterir.

Ve ana composer.json dosyasındaki PHPUnit versiyonunu 5.3.5'e (PHP7'yi destekleyen ve kamu alaycı yöntemlere sahip (Magento 2'nin kendi testlerinin gerektirdiği) en son sürüm) güncellemeye ne dersiniz?

Diğer modüllerde ve çekirdekteki testler yalnızca PHPUnit 4.1 ile test edildiğinden ve CI'de yanlış hatalarla karşılaşabileceğinizden bu sorunlu olabilir. PHPUnit'in paketlenmiş sürümüne bağlı kalmanın en iyisi olduğunu düşünüyorum. @maksek, PHPUnit'i güncelleyeceklerini söyledi, ancak bunun için ETA yok.


Mockery kütüphanesini kullanarak, PHPUnit 4.1 ile çalışan PHP7 gerektiren bir sınıfın test çiftine sahip bir test örneği:

<?php

declare(strict_types = 1);

namespace Example\Php7\Test\Unit;

// Foo is a class that will not work with the mocking library bundled with PHPUnit 4.1 
// The test below creates a mock of this class using mockery and uses it in a test run by PHPUnit 4.1
class Foo
{
    public function isSomethingTrue(string $baz): bool
    {
        return 'something' === $baz; 
    }
}

// This is another class that uses PHP7 scalar argument types and a return type.
// It is the system under test in the example test below.
class Bar
{
    private $foo;

    public function __construct(Foo $foo)
    {
        $this->foo = $foo;
    }

    public function useFooWith(string $s): bool
    {
        return $this->foo->isSomethingTrue($s);
    }
}

// This is an example test that runs with PHPUnit 4.1 and uses mockery to create a test double
// of a class that is only compatible with PHP7 and younger.
class MockWithReturnTypeTest extends \PHPUnit_Framework_TestCase
{
    protected function tearDown()
    {
        \Mockery::close();
    }

    public function testPHPUnitVersion()
    {
        // FYI to show this test runs with PHPUnit 4.1
        $this->assertSame('4.1.0', \PHPUnit_Runner_Version::id());
    }

    public function testPhpVersion()
    {
        // FYI this test runs with PHP7
        $this->assertSame('7.0.15', \PHP_VERSION);
    }

    // Some nonsensical example test using a mock that has methods with
    // scalar argument types and PHP7 return types.
    public function testBarUsesFoo()
    {
        $stubFoo = \Mockery::mock(Foo::class);
        $stubFoo->shouldReceive('isSomethingTrue')->with('faz')->andReturn(false);
        $this->assertFalse((new Bar($stubFoo))->useFooWith('faz'));
    }
}

Mockery, PHPUnit 4.1.0'ın PHP7 tip ipuçlarını doğru şekilde kullanamama sorununu 'çözüyor mu?' Ve anonim sınıfların alay etmenin faydaları nelerdir? Ve ana composer.jsondosyadaki PHPUnit sürümünü 5.3.5'e (PHP7'yi destekleyen ve genel alaycı yöntemleri olan (Magento 2'nin kendi testlerinin gerektirdiği) en son sürüm) güncellemeye ne dersiniz ? Şimdi çok daha fazla soru ...
Giel Berkers

Sorunuza cevap olarak cevabımı güncelledi @GielBerkers
Vinai

Cevabınız için teşekkürler. Şimdi tamamen açık! Sanırım gidip Mockery'i deneyeceğim. Anonim sınıflar, Mockery'nin zaten sunduğu birçok şeyi yeniden icat etmem gerekiyor gibi görünüyor. İlk önce PHPUnit'in temellerini öğrenmek ve oradan devam etmek istedim. Bence şimdi orada saat var.
Giel Berkers

Harika! Harika bir kütüphane olan Mockery'yi keşfetmenin tadını çıkarın. Sen onun yanındayken, belki de hamcrest'i, bir iddia kitaplığını da kontrol et - Mockery ile otomatik olarak kurulacak.
Vinai

3

Şu anda Magento 2, bir sonraki PHP sürümlerini destekliyor:

"php": "~5.6.5|7.0.2|7.0.4|~7.0.6"

Bu, Magento Ekibi tarafından yazılan tüm kodların desteklenen her sürümde çalıştığı anlamına gelir.

Bu nedenle Magento Takımı sadece PHP 7 özelliklerini kullanmaz. PHP 5.6 özellikleri PHPUnit 4.1.0 ile kaplanabilir.

Kendi kodunuzu yazarak istediğiniz her şeyi yapabilir ve istediğiniz şekilde testler yazabilirsiniz. Ancak, gereklilik ihlali nedeniyle uzantınızı Magento Marketplace'te yayınlayamayacağınıza inanıyorum.


Aslında, PHPUnit 5.7, PHP 5.6, PHP 7.0 ve PHP 7.1'de desteklenmektedir. PHPUnit 4.8, PHP 5.3 - 5.6'da desteklenmiştir. Bu yüzden Magento 2, PHP 5.6'yı desteklese de, yine de PHPUnit 5.7'ye yükseltebilir.
Vinai
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.