Кофигурация проекта является довольно критичным функционалом, который, однако, часто забывают тестировать. В Symfony2 используется система сервисов, реализующая паттерн dependency injection. И правильную обработку параметров и передачу их в контейнер необходимо тестировать так же, как и любой другой код.
Для примера я возьму свой последний проект - HTML5CacheBundle.
Бандл реализует возможность использовать HTML5 Application Cache в проекте на Symfony2, для этого нужно указать пути к статическим файлам, которые нужно кешировать. Учтена возможность работы с локальным CDN (в т.ч. SSL). Также можно указать сторонние библиотеки, такие как jQuery или Twitter Bootstrap.
Описание всех параметров можно прочитать, перейдя по вышеуказанной ссылке. Но основные параметры конфигурации я приведу ниже для более глубокого понимания цели:
#HTML5CacheBundl html5_cache: cdn: cdn.site.com http: true https: false custom_urls: - https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js - ...
Для использования конфигураций в системе необходимо создать каталог DependencyInjection и разместить в нем файл Configuration, который содержит дерево конфигурации, и HTML5CacheExtension, который добавляет в контейнер наши параметры.
Приведу основные моменты в вышеуказанных файлах.
Configuration:
/** * Class Configuration * @package Evheniy\HTML5CacheBundle\DependencyInjection */ class Configuration implements ConfigurationInterface { /** * @return TreeBuilder */ public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('html5_cache'); $rootNode ->children() ->scalarNode('cdn')->defaultValue('')->end() ->booleanNode('http')->defaultTrue()->end() ->booleanNode('https')->defaultTrue()->end() ->arrayNode('custom_paths')->prototype('scalar')->end() ->end() ->end(); return $treeBuilder; } }
HTML5CacheExtension:
/** * Class HTML5CacheBundle * * @package Evheniy\HTML5CacheBundle\DependencyInjection */ class HTML5CacheExtension extends Extension { /** * @param array $configs * @param ContainerBuilder $container */ public function load(array $configs, ContainerBuilder $container) { $processor = new Processor(); $configuration = new Configuration(); $config = $processor->processConfiguration($configuration, $configs); $container->setParameter('html5_cache', $config); ...
Как видно в первом файле я описал дерево возможных комбинаций параметров, а второй файл (само расширение) получает параметры из контейнера и обрабатывает их с учетом нашего дерева.
Осталось протестировать полученный код. В бандле в директории Tests нужно создать одноименную папку DependencyInjection, в которой будет распологаться наш файл тестов HTML5CacheExtensionTest.
Для тестирования я выбрал бандл с небольшим набором параметров, в котром большая часть параметров имеет значения по умолчанию. Поэтому тестирование сводится к проверке параметров по умолчанию и проверке установленных параметров.
Для тестирования параметров по умолчанию достаточно загрузить расширение без указанных параметров:
protected function setUp() { $this->extension = new HTML5CacheExtension(); $this->container = new ContainerBuilder(); $this->container->registerExtension($this->extension); } public function testWithoutConfiguration() { $this->container->loadFromExtension($this->extension->getAlias()); $this->container->compile(); $this->assertTrue($this->container->hasParameter('html5_cache')); $html5Cache = $this->container->getParameter('html5_cache'); $this->assertEmpty($html5Cache['cdn']); $this->assertTrue($html5Cache['http']); $this->assertTrue($html5Cache['https']); }
Здесь я проверяю наличие 3 параметров и их значения.
Для тестирования параметров я создал файл Fixtures/test.yml:
html5_cache: cdn: //cdn.site.com http: false https: false
Этот файл необходимо загрузить и проверить значения
/** * @param ContainerBuilder $container * @param string $resource */ protected function loadConfiguration(ContainerBuilder $container, $resource) { $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/Fixtures/')); $loader->load($resource . '.yml'); } /** * Test normal config */ public function testTest() { $this->loadConfiguration($this->container, 'test'); $this->container->compile(); $this->assertTrue($this->container->hasParameter('html5_cache')); $html5Cache = $this->container->getParameter('html5_cache'); $this->assertNotEmpty($html5Cache['cdn']); $this->assertEquals($html5Cache['cdn'], 'cdn.site.com'); $this->assertEmpty($html5Cache['https']); $this->assertFalse($html5Cache['https']); $this->assertEmpty($html5Cache['http']); $this->assertFalse($html5Cache['http']); }
Для 100% покрытия кода можно проверить имя расширения:
public function testGetAlias() { $this->assertEquals($this->extension->getAlias(), 'html5_cache'); }
Как видим нет ничего сложного, чтоб выпускать код более высокого качества и стремиться к максимальному покрытию кода тестами.