Vamos falar sobre como parar a copiar e colar entre projetos e transferir o código para um pacote reutilizável de plug-in Symfony 5. Uma série de artigos resumindo minha experiência com pacotes configuráveis, na prática, criará um pacote mínimo e refatorará um aplicativo de demonstração para testes e o ciclo de lançamento de pacotes.
Na parte anterior, criamos a configuração do pacote . Neste artigo, analisaremos como testar um pacote configurável, escrever alguns testes e criar um micro aplicativo dentro do pacote configurável para executá-los.
Se você não estiver concluindo consistentemente o tutorial, faça o download do aplicativo no repositório e alterne para a ramificação de 5 configurações .
Instruções para instalar e iniciar o projeto em um arquivo README.md. Você encontrará a versão final do código para este artigo na ramificação de 6 testes .
Portando testes para um pacote configurável
Antes da refatoração, dois testes já foram gravados: um teste de unidade de um dos serviços e um teste funcional do controlador.
Temos um aplicativo primitivo no qual a camada de infraestrutura (DB) não é separada da lógica do domínio: os testes usam um banco de dados sqlite temporário.
Verifique se os testes funcionam:
./vendor/bin/simple-phpunit
Error: Class 'App\Service\EventExporter\Exporters\GoogleCalendarExporter' not found
Os testes deixaram os nomes de namespace App\restantes do código até que ele fosse transferido para o pacote.
Nos dois testes, fixamos o espaço para nome bravik\CalendarBundlee o executamos novamente.
Os testes devem passar com sucesso.
Na raiz do pacote configurável, crie uma pasta tests( bundles/CalendarBundle/tests) e mova a pasta de tests/Serviceteste de unidade para lá . ControllerTransferimos o teste funcional na pasta um pouco mais tarde.
Executando testes de unidade de um pacote
Para executar o teste, precisamos instalar o PHPUnit dentro do pacote:
cd bundles/CalendarBundle
composer require symfony/phpunit-bridge --dev
Isso adicionará a unidade PHP como uma dependência do desenvolvedor ao composer.jsonpacote e também criará um arquivo composer.lock. Não precisamos dele em pacotes: crie um .gitignorearquivo e adicione-o lá.
Unidade PHP pronta para uso não funcionará. Você precisa configurá-lo: especifique onde estão os testes e conecte o carregador automático do 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 - .
Você encontrará a versão final do código para este artigo na ramificação de 6 testes .
No próximo artigo, falaremos sobre como liberar novas liberações de pacotes configuráveis sem sofrimento e sofrimento, como organizar o processo de instalação inicial e atualização do pacote configurável.
Outros artigos da série:
Parte 1. O pacote mínimo
Parte 2. Retiramos o código e os modelos no pacote
Parte 3. Integração do pacote com o host: modelos, estilos, JS
Parte 4. Interface para expandir o pacote
Parte 5. Parâmetros e configuração
Parte 6. Teste, microaplicação dentro do pacote
Parte 7 Ciclo de lançamento, instalação e atualização