Lassen Sie uns darüber sprechen, wie Sie das Kopieren und Einfügen zwischen Projekten stoppen und den Code in ein wiederverwendbares Plug-In-Bundle Symfony 5 übertragen können. Eine Reihe von Artikeln, die meine Erfahrungen mit Bundles zusammenfassen, wird in der Praxis von der Erstellung eines minimalen Bundles über die Umgestaltung einer Demo-Anwendung bis hin zu Tests und dem Bundle-Release-Zyklus durchgeführt.
Im vorherigen Teil haben wir die Bundle-Konfiguration erstellt . In diesem Artikel analysieren wir, wie ein Bundle getestet, einige Tests geschrieben und eine Mikroanwendung innerhalb des Bundles erstellt wird, um sie auszuführen.
Wenn Sie das Lernprogramm nicht konsequent abschließen, laden Sie die Anwendung aus dem Repository herunter und wechseln Sie zum Zweig mit 5 Konfigurationen .
Anweisungen zum Installieren und Starten des Projekts in einer Datei README.md
. Die endgültige Version des Codes für diesen Artikel finden Sie im 6-Test- Zweig .
Portierungstests in ein Bundle
Vor dem Refactoring wurden bereits 2 Tests geschrieben: ein Komponententest eines der Dienste und ein Funktionstest des Controllers.
Wir haben eine primitive Anwendung, in der die Infrastrukturschicht (DB) nicht von der Domänenlogik getrennt ist: Tests verwenden eine temporäre SQLite-Datenbank.
Überprüfen Sie, ob die Tests funktionieren:
./vendor/bin/simple-phpunit
Error: Class 'App\Service\EventExporter\Exporters\GoogleCalendarExporter' not found
Bei den Tests blieben die Namespace-Namen App\
im Code, bis sie in das Bundle übertragen wurden.
Korrigieren Sie in beiden Tests den Namespace bravik\CalendarBundle
und führen Sie ihn erneut aus.
Tests müssen erfolgreich bestanden werden.
Erstellen Sie im Stammverzeichnis des Bundles einen Ordner tests
( bundles/CalendarBundle/tests
) und verschieben Sie den tests/Service
Unit-Test- Ordner dorthin . Controller
Den Funktionstest übertragen wir etwas später in den Ordner .
Ausführen von Komponententests aus einem Bundle
Um den Test auszuführen, müssen wir PHPUnit im Bundle installieren:
cd bundles/CalendarBundle
composer require symfony/phpunit-bridge --dev
Dadurch wird die PHP-Einheit als Entwicklungsabhängigkeit zum composer.json
Bundle hinzugefügt und eine Datei erstellt composer.lock
. Wir brauchen es nicht in Bundles: Erstellen Sie eine .gitignore
Datei und fügen Sie sie dort hinzu.
Die sofort einsatzbereite PHP-Einheit funktioniert nicht. Sie müssen es konfigurieren: Geben Sie an, wo die Tests liegen, und verbinden Sie den Composer-Autoloader.
- 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 - .
Die endgültige Version des Codes für diesen Artikel finden Sie im 6-Test- Zweig .
Im nächsten Artikel werden wir darüber sprechen, wie neue Bundle-Releases ohne Schmerzen und Leiden veröffentlicht werden und wie der Prozess der Erstinstallation und Aktualisierung des Bundles organisiert wird.
Andere Artikel in der Reihe:
Teil 1. Das minimale Bundle
Teil 2. Wir nehmen den Code und die Vorlagen im Bundle heraus.
Teil 3. Integration des Bundles mit dem Host: Vorlagen, Stile, JS
Teil 4. Schnittstelle zum Erweitern des Bundles
Teil 5. Parameter und Konfiguration
Teil 6. Testen, Mikroanwendung innerhalb des Bundles
Teil 7 Release-Zyklus, Installation und Update