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\CalendarBundle
e 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/Service
teste de unidade para lá . Controller
Transferimos 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.json
pacote e também criará um arquivo composer.lock
. Não precisamos dele em pacotes: crie um .gitignore
arquivo 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