كيفية إعادة استخدام الكود مع حزم symfony 5؟ الجزء 6. الاختبار

لنتحدث عن كيفية إيقاف النسخ واللصق بين المشاريع ونقل الشفرة إلى حزمة مكون إضافي symfony 5. يمكن إعادة استخدامها. ستؤدي سلسلة من المقالات التي تلخص تجربتي مع الحزم عمليًا إلى إنشاء الحد الأدنى من الحزم وإعادة صياغة التطبيق التجريبي إلى الاختبارات ودورة إصدار الحزمة.


في الجزء السابق ، أنشأنا تكوين الحزمة . في هذه المقالة ، سنقوم بتحليل كيفية اختبار حزمة ، وكتابة بعض الاختبارات وإنشاء تطبيق صغير داخل الحزمة لتشغيلها.


محتوى المسلسل

إذا كنت لا تكمل البرنامج التعليمي بالتسلسل ، فقم بتنزيل التطبيق من المستودع وانتقل إلى فرع التكوين 5 .


تعليمات تثبيت وبدء المشروع في ملف README.md. ستجد النسخة النهائية من التعليمات البرمجية لهذه المقالة في فرع الاختبار 6 .


اختبارات النقل لحزمة


قبل إعادة الهيكلة ، تم بالفعل كتابة اختبارين: اختبار وحدة لإحدى الخدمات واختبار وظيفي لجهاز التحكم.


لدينا تطبيق بدائي لا يتم فيه فصل طبقة البنية التحتية (DB) عن منطق المجال: تستخدم الاختبارات قاعدة بيانات sqlite مؤقتة.


تحقق مما إذا كانت الاختبارات تعمل:


./vendor/bin/simple-phpunit

Error: Class 'App\Service\EventExporter\Exporters\GoogleCalendarExporter' not found

تركت الاختبارات أسماء مساحة الاسم App\المتبقية من الرمز حتى تم نقلها إلى الحزمة.


في كلا الاختبارين ، قم بإصلاح مساحة الاسم bravik\CalendarBundleوقم بتشغيلها مرة أخرى.
يجب أن تجتاز الاختبارات بنجاح.


في جذر الحزمة ، قم بإنشاء مجلد tests( bundles/CalendarBundle/tests) tests/Serviceوانقل مجلد اختبار الوحدة هناك . نقوم Controllerبنقل الاختبار الوظيفي في المجلد بعد ذلك بقليل.


إجراء اختبارات الوحدة من حزمة


لإجراء الاختبار ، نحتاج إلى تثبيت PHPUnit داخل الحزمة:


cd bundles/CalendarBundle
composer require symfony/phpunit-bridge --dev

سيؤدي ذلك إلى إضافة وحدة PHP باعتبارها تبعية مطورة composer.jsonللحزمة ، وكذلك إنشاء ملف composer.lock. لا نحتاجه في حزم: قم بإنشاء .gitignoreملف وإضافته هناك.


لن تعمل وحدة PHP خارج منطقة الجزاء. تحتاج إلى تهيئته: حدد مكان الاختبارات وتوصيل برنامج التحميل التلقائي للملحن.


- 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()
    {
        // TODO: Implement registerBundles() method.
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        // TODO: Implement registerContainerConfiguration() method.
    }
}

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");
    // Assertion on response
    // ...
}

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 - .


ستجد النسخة النهائية من التعليمات البرمجية لهذه المقالة في فرع الاختبار 6 .


في المقالة التالية سنتحدث عن كيفية إطلاق إصدارات حزمة جديدة دون ألم ومعاناة ، وكيفية تنظيم عملية التثبيت الأولي وتحديث الحزمة.


مقالات أخرى في السلسلة:


الجزء 1. الحد الأدنى للحزمة
الجزء 2. نأخذ الشفرة والقوالب في الحزمة
الجزء 3. تكامل الحزمة مع المضيف: القوالب ، الأنماط ، JS
الجزء 4. واجهة لتوسيع الحزمة
الجزء 5. المعلمات والتكوين
الجزء 6. الاختبار ، التطبيق الجزئي داخل الحزمة
الجزء 7 دورة الإصدار والتثبيت والتحديث


All Articles