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.
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\CalendarBundle
et 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/Service
test unitaire. Nous Controller
transfé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.json
bundle et créera également un fichier composer.lock
. Nous n'en avons pas besoin en bundles: créez un .gitignore
fichier 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()
{
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
}
}
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");
}
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