Bagaimana cara menggunakan kembali kode dengan bundel symfony 5? Bagian 6. Pengujian

Mari kita bicara tentang cara menghentikan copy-paste antara proyek dan mentransfer kode ke bundel plug-in symfony 5. yang dapat digunakan kembali. Serangkaian artikel yang merangkum pengalaman saya dengan bundel akan memimpin dalam praktik dari membuat bundel minimal dan refactoring aplikasi demo ke pengujian dan siklus rilis bundel.


Di bagian sebelumnya, kami membuat konfigurasi bundel . Pada artikel ini, kami akan menganalisis cara menguji bundel, menulis beberapa tes, dan membuat aplikasi mikro di dalam bundel untuk menjalankannya.



Jika Anda tidak secara konsisten menyelesaikan tutorial, maka unduh aplikasi dari repositori dan alihkan ke cabang 5-konfigurasi .


Petunjuk untuk menginstal dan memulai proyek dalam file README.md. Anda akan menemukan versi final kode untuk artikel ini di cabang 6-pengujian .


Porting tes ke bundel


Sebelum refactoring, 2 tes sudah ditulis: tes unit dari salah satu layanan dan tes fungsional controller.


Kami memiliki aplikasi primitif di mana lapisan infrastruktur (DB) tidak dipisahkan dari logika domain: tes menggunakan database sqlite sementara.


Periksa apakah tes bekerja:


./vendor/bin/simple-phpunit

Error: Class 'App\Service\EventExporter\Exporters\GoogleCalendarExporter' not found

Tes meninggalkan nama namespace yang App\tersisa dari kode sampai ditransfer ke bundel.


Di kedua pengujian, perbaiki namespace bravik\CalendarBundledan jalankan kembali.
Tes harus lulus dengan sukses.


Di root bundel, buat folder tests( bundles/CalendarBundle/tests) dan pindahkan folder tests/Servicetes unit di sana . Kami Controllermentransfer tes fungsional dalam folder beberapa saat kemudian.


Menjalankan tes unit dari bundel


Untuk menjalankan tes, kita perlu menginstal PHPUnit di dalam bundel:


cd bundles/CalendarBundle
composer require symfony/phpunit-bridge --dev

Ini akan menambahkan Unit PHP sebagai ketergantungan dev ke composer.jsonbundel, dan juga membuat file composer.lock. Kami tidak membutuhkannya dalam bundel: buat .gitignorefile dan tambahkan di sana.


Unit PHP di luar kotak tidak akan berfungsi. Anda harus mengonfigurasinya: tentukan di mana tes terletak dan sambungkan autoloader komposer.


- phpunit.xml.dist.


, Symfony-, 1 bootstrap:


<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="bin/.phpunit/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="./vendor/autoload.php"
>

bootstrap composer, PHPUnit .


:


./vendor/bin/simple-phpunit

!


: - .


โ€ฆ ?
.



, 2 .
, โ€” , โ€” -.
.


, ,
-.


- Symfony โ€” Kernel symfony/http-kernel.
, , .


. , , Symfony DI-, . symfony/framework-bundle, http-kernel.


composer require symfony/framework-bundle 

tests/App TestingKernel .


Symfony\Component\HttpKernel\Kernel , :


<?php
namespace bravik\CalendarBundle\Tests\App;

use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;

class TestingKernel extends Kernel
{
    public function __construct()
    {
        parent::__construct('test', false);
    }

    public function registerBundles()
    {
        // TODO: Implement registerBundles() method.
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        // TODO: Implement registerContainerConfiguration() method.
    }
}

composer bravik\CalendarBundle\Tests\App.


: 'test', . , .


registerBundles() . :


public function registerBundles()
{
    return [
      new CalendarBundle() 
    ];
}

registerContainerConfiguration() DI-.
.


symfony/router. , .


. src/Kernel -:


class Kernel extends BaseKernel
{
    use MicroKernelTrait;

    //...

    protected function configureRoutes(RouteCollectionBuilder $routes): void
    {
        //...
        $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
    }
}

, Symfony- ยซยป MicroKernelTrait.


registerContainerConfiguration(),
-:


  • configureContainer()
  • configureRoutes(), .

:


  • TestingKernel registerContainerConfiguration(),
  • use MicroKernelTrait;
  • .

configureRoutes() config/routes.yaml :


protected function configureRoutes(RouteCollectionBuilder $routes)
{
    $routes->import(__DIR__.'/../../config/routes.yaml');
}

yaml, :


composer require symfony/yaml

.


?



tests/Controller/EventControllerTest.


HTTP . HTTP-. , .


Symfony Request, . index.php:


$request = Request::createFromGlobals();
$response = $kernel->handle($request);

, .


, Symfony HttpKernelBrowser :


composer require symfony/browser-kit --dev

:


public static function createClient()
{
    $kernel = new TestingKernel();
    return new HttpKernelBrowser($kernel);
}

public function testSomeAction()
{
    $client = static::createClient();
    $response = $client->request("/some/action");
    // Assertion on response
    // ...
}

HttpKernelBrowser. $client->request() .


, , WebTestCase, Symfony. createClient(), , createKernel(), .


, , โ€” . KERNEL_CLASS phpunit.xml.dist:


<php>
    <server name="APP_ENV" value="test" force="true" />
    <server name="KERNEL_CLASS" value="bravik\CalendarBundle\Tests\App\TestingKernel"
            force="true" />
    <!-- ... -->
</php>

:


./vendor/bin/simple-phpunit tests/Controller/EventControllerTest.php

...


LogicException: Container extension "framework" is not registered

MicroKernelTrait. DI- ยซ-ยป, framework.


FrameworkBundle. :


    public function registerBundles()
    {
        return [
            new FrameworkBundle(),
            new CalendarBundle()
        ];
    }

:


InvalidArgumentException: Cannot determine controller argument for "bravik\CalendarBundle\Controller\EditorController::new()": the $entityManager argument is type-hinted with the non-existent class or interface: "Doctrine\ORM\EntityManagerInterface".

- ? EditorController?


new CalendarBundle() TestingKernel, services.yaml, .


autowiring Symfony . typehints , Symfony typehints .


, , TestingKernel.


:


composer require doctrine/orm doctrine/doctrine-bundle symfony/twig-bundle
composer require doctrine/doctrine-fixtures-bundle liip/test-fixtures-bundle --dev

TestingKernel:


public function registerBundles()
{
    return [
        new DoctrineBundle(),
        new DoctrineFixturesBundle(),
        new LiipTestFixturesBundle(),
        new TwigBundle(),
        //..
    ];
}

: tests/App/config/config.yaml:


#    
# @see https://symfony.com/doc/current/reference/configuration/framework.html#test
framework:
  test:   true

doctrine:
  #  SQLITE     var/test.db
  dbal:
    driver: pdo_sqlite
    path: "%kernel.cache_dir%/test.db"

  #  ORM- 
  orm:
    auto_generate_proxy_classes: true
    naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
    auto_mapping: true

calendar:
  enable_soft_delete: true

services:
  #  Twig,  mock-   webpack encore,
  #    
  bravik\CalendarBundle\Tests\App\TwigWebpackSuppressor:
    tags: ['twig.extension']

  #       
  bravik\CalendarBundle\Tests\Fixtures\:
    resource: '../../Fixtures'
    tags: ['doctrine.fixture.orm']

, packages, . Framework, Doctrine, .


TestingKernel:


protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
    $loader->load(__DIR__.'/config/config.yaml', 'yaml');
}

(!) , , var Symfony . .gitignore.

, dev . - , โ€” !

, - !


, , .



, Symfony - .


Anda akan menemukan versi final kode untuk artikel ini di cabang 6-pengujian .


Pada artikel selanjutnya kita akan berbicara tentang bagaimana melepaskan rilis bundel baru tanpa rasa sakit dan penderitaan, bagaimana mengatur proses instalasi awal dan memperbarui bundel.


Artikel lain dalam seri:


Bagian 1. Bundel minimum
Bagian 2. Kami mengeluarkan kode dan templat dalam bundel
Bagian 3. Integrasi bundel dengan host: templat, gaya, JS
Bagian 4. Antarmuka untuk memperluas bundel
Bagian 5. Parameter dan konfigurasi
Bagian 6. Pengujian, aplikasi mikro di dalam bundel
Bagian 7 Lepaskan siklus, instalasi, dan perbarui


All Articles