Hablemos sobre cómo detener el copiar y pegar entre proyectos y transferir el código a un paquete de plug-in reutilizable Symfony 5. Una serie de artículos que resumen mi experiencia con los paquetes se llevarán a cabo en la práctica desde la creación de un paquete mínimo y la refactorización de una aplicación de demostración para las pruebas y el ciclo de lanzamiento del paquete.
En la parte anterior, creamos la configuración del paquete . En este artículo, analizaremos cómo probar un paquete, escribir algunas pruebas y crear una micro aplicación dentro del paquete para ejecutarlas.
Si no está completando constantemente el tutorial, descargue la aplicación del repositorio y cambie a la rama de 5 configuraciones .
Instrucciones para instalar e iniciar el proyecto en un archivo README.md. Encontrará la versión final del código para este artículo en la rama de 6 pruebas .
Portar pruebas a un paquete
Antes de refactorizar, ya se escribieron 2 pruebas: una prueba unitaria de uno de los servicios y una prueba funcional del controlador.
Tenemos una aplicación primitiva en la que la capa de infraestructura (DB) no está separada de la lógica del dominio: las pruebas usan una base de datos sqlite temporal.
Comprueba si las pruebas funcionan:
./vendor/bin/simple-phpunit
Error: Class 'App\Service\EventExporter\Exporters\GoogleCalendarExporter' not found
Las pruebas dejaron los nombres de espacio de nombres App\restantes del código hasta que se transfirió al paquete.
En ambas pruebas, arregle el espacio de nombres bravik\CalendarBundley ejecútelo nuevamente.
Las pruebas deben pasar con éxito.
En la raíz del paquete, cree una carpeta tests( bundles/CalendarBundle/tests) y mueva la carpeta de tests/Serviceprueba de la unidad allí . ControllerTransferimos la prueba funcional en la carpeta un poco más tarde.
Ejecución de pruebas unitarias desde un paquete
Para ejecutar la prueba, necesitamos instalar PHPUnit dentro del paquete:
cd bundles/CalendarBundle
composer require symfony/phpunit-bridge --dev
Esto agregará la Unidad PHP como una dependencia de desarrollo al composer.jsonpaquete, y también creará un archivo composer.lock. No lo necesitamos en paquetes: cree un .gitignorearchivo y agréguelo allí.
La unidad PHP lista para usar no funcionará. Debe configurarlo: especifique dónde se encuentran las pruebas y conecte el autocargador del compositor.
- 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 - .
Encontrará la versión final del código para este artículo en la rama de 6 pruebas .
En el próximo artículo hablaremos sobre cómo lanzar nuevos lanzamientos de paquetes sin dolor ni sufrimiento, cómo organizar el proceso de instalación inicial y actualización del paquete.
Otros artículos de la serie:
Parte 1. El paquete mínimo
Parte 2. Sacamos el código y las plantillas en el paquete
Parte 3. Integración del paquete con el host: plantillas, estilos, JS
Parte 4. Interfaz para expandir el paquete
Parte 5. Parámetros y configuración
Parte 6. Pruebas, microaplicación dentro del paquete
Parte 7 Ciclo de lanzamiento, instalación y actualización.