Comment réutiliser du code avec des bundles symfony 5? Partie 6. Test

Parlons de la façon d'arrĂȘter le copier-coller entre les projets et de transfĂ©rer le code dans un bundle de plug-ins rĂ©utilisable Symfony 5. Une sĂ©rie d'articles rĂ©sumant mon expĂ©rience avec les bundles permettra en pratique de crĂ©er un bundle minimal et de refactoriser une application de dĂ©monstration en tests et en cycle de publication de bundle.


Dans la partie précédente, nous avons créé la configuration du bundle . Dans cet article, nous allons analyser comment tester un bundle, écrire des tests et créer une micro application à l'intérieur du bundle pour les exécuter.


Contenu de la série

Si vous ne suivez pas systématiquement le didacticiel, téléchargez l'application à partir du référentiel et passez à la branche 5-configuration .


Instructions pour installer et démarrer le projet dans un fichier README.md. Vous trouverez la version finale du code de cet article dans la branche 6-testing .


Portage de tests sur un bundle


Avant refactoring, 2 tests étaient déjà écrits: un test unitaire d'un des services et un test fonctionnel du contrÎleur.


Nous avons une application primitive dans laquelle la couche infrastructure (DB) n'est pas séparée de la logique du domaine: les tests utilisent une base de données sqlite temporaire.


VĂ©rifiez si les tests fonctionnent:


./vendor/bin/simple-phpunit

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

Les tests ont laissé les noms d'espace de noms App\restants du code jusqu'à ce qu'il soit transféré dans le bundle.


Dans les deux tests, fixez l'espace de noms bravik\CalendarBundleet réexécutez-le.
Les tests doivent réussir.


À la racine du bundle, crĂ©ez un dossier tests( bundles/CalendarBundle/tests) et dĂ©placez-y le dossier de tests/Servicetest unitaire. Nous ControllertransfĂ©rons le test fonctionnel dans le dossier un peu plus tard.


Exécution de tests unitaires à partir d'un bundle


Pour exécuter le test, nous devons installer PHPUnit à l'intérieur du bundle:


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

Cela ajoutera l'unité PHP en tant que dépendance de développement au composer.jsonbundle et créera également un fichier composer.lock. Nous n'en avons pas besoin en bundles: créez un .gitignorefichier et ajoutez-le là.


L'unitĂ© PHP prĂȘte Ă  l'emploi ne fonctionnera pas. Vous devez le configurer: spĂ©cifiez oĂč se trouvent les tests et connectez l'autochargeur du composeur.


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


Vous trouverez la version finale du code de cet article dans la branche 6-testing .


Dans le prochain article, nous parlerons de la façon de publier de nouvelles versions de bundle sans douleur et souffrance, comment organiser le processus d'installation initiale et de mise à jour du bundle.


Autres articles de la série:


Partie 1. Le bundle minimum
Partie 2. Nous sortons le code et les modĂšles du bundle
Partie 3. Intégration du bundle avec l'hÎte: modÚles, styles, JS
Partie 4. Interface pour développer le bundle
Partie 5. ParamĂštres et configuration
Partie 6. Test, microapplication à l'intérieur du bundle
Partie 7 Cycle de publication, installation et mise Ă  jour


All Articles