Кофигурация проекта является довольно критичным функционалом, который, однако, часто забывают тестировать. В 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');
}Как видим нет ничего сложного, чтоб выпускать код более высокого качества и стремиться к максимальному покрытию кода тестами.