diff --git a/AtoumAtoumBundle.php b/AtoumAtoumBundle.php index 3fab33e..04c1f85 100644 --- a/AtoumAtoumBundle.php +++ b/AtoumAtoumBundle.php @@ -3,7 +3,37 @@ namespace atoum\AtoumBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use atoum\AtoumBundle\DependencyInjection\AtoumAtoumExtension; +use atoum\AtoumBundle\DependencyInjection\Compiler\BundleDirectoriesResolverPass; +/** + * AtoumAtoumBundle + * + * @uses Bundle + * @author Stephane PY + */ class AtoumAtoumBundle extends Bundle { + /** + * {@inheritdoc} + */ + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->addCompilerPass(new BundleDirectoriesResolverPass()); + } + + /** + * {@inheritdoc} + */ + public function getContainerExtension() + { + if (null === $this->extension) { + $this->extension = new AtoumAtoumExtension; + } + + return $this->extension; + } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 653b5e2..21f39f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ * master (next 1.1.0) + * Add command to launch tests on bundles. * Add fluent interface for controllers testing * Add support for Faker (https://github.com/fzaninotto/Faker) * Compatibility break @@ -9,4 +10,4 @@ * 1.0.0 (2012) * Move the bundle to atoum vendor namespace - * Add ControllerTest class \ No newline at end of file + * Add ControllerTest class diff --git a/Command/AtoumCommand.php b/Command/AtoumCommand.php new file mode 100644 index 0000000..a791819 --- /dev/null +++ b/Command/AtoumCommand.php @@ -0,0 +1,141 @@ + + */ +class AtoumCommand extends ContainerAwareCommand +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('atoum') + ->setDescription('Launch atoum tests.') + ->setHelp(<<./app/console atoum AcmeFooBundle + +Launch tests of many bundles: + +./app/console atoum AcmeFooBundle bundle_alias_extension ... + +Launch tests of all bundles defined on configuration: + +./app/console atoum + +EOF + ) + ->addArgument('bundles', InputArgument::IS_ARRAY, 'Launch tests of these bundles.') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $runner = new runner('atoum'); + + $bundles = $input->getArgument('bundles'); + if (count($bundles) > 0) { + $self = $this; + $bundles = array_map(function($v) use ($self) { + return $self->extractBundleConfigurationFromKernel($v); + }, $bundles); + } else { + $bundles = $this->getContainer()->get('atoum.configuration.bundle.container')->all(); + } + + foreach ($bundles as $bundle) { + $directories = array_filter($bundle->getDirectories(), function($dir) { + return is_dir($dir); + }); + + if (empty($directories)) { + $output->writeln(sprintf('There is no test found on "%s".', $bundle->getName())); + } + + foreach ($directories as $directory) { + $runner->addTestAllDirectory($directory); + } + } + + if (count($runner->getTestAllDirectories()) == 0) { + $output->writeln('There is no test to launch.'); + } else { + $runner->run(array( + '--test-all' + )); + } + } + + /** + * @param string $name name + * + * @return BundleConfiguration + */ + public function extractBundleConfigurationFromKernel($name) + { + $kernelBundles = $this->getContainer()->get('kernel')->getBundles(); + $bundle = null; + + if (preg_match('/Bundle$/', $name)) { + if (!isset($kernelBundles[$name])) { + throw new \LogicException(sprintf('Bundle "%s" does not exists or is not activated.', $name)); + } + + $bundle = $kernelBundles[$name]; + } else { + foreach ($kernelBundles as $kernelBundle) { + $extension = $kernelBundle->getContainerExtension(); + + if ($extension && $extension->getAlias() == $name) { + $bundle = $kernelBundle; + break; + } + } + + if (null === $bundle) { + throw new \LogicException(sprintf('Bundle with alias "%s" does not exists or is not activated.', $name)); + } + } + + $bundleContainer = $this->getContainer()->get('atoum.configuration.bundle.container'); + + if ($bundleContainer->has($bundle->getName())) { + return $bundleContainer->get($bundle->getName()); + } else { + return new BundleConfiguration($bundle->getName(), $this->getDefaultDirectoriesForBundle($bundle)); + } + } + + /** + * @param Bundle $bundle bundle + * + * @return array + */ + public function getDefaultDirectoriesForBundle(Bundle $bundle) + { + return array( + sprintf('%s/Tests/Units', $bundle->getPath()), + sprintf('%s/Tests/Controller', $bundle->getPath()), + ); + } +} diff --git a/Configuration/Bundle.php b/Configuration/Bundle.php new file mode 100644 index 0000000..e85d699 --- /dev/null +++ b/Configuration/Bundle.php @@ -0,0 +1,47 @@ + + */ +class Bundle +{ + /** + * @var string + */ + protected $name; + + /** + * @var array + */ + protected $directories = array(); + + /** + * @param string $name name + * @param array $directories directories + */ + public function __construct($name, array $directories) + { + $this->name = $name; + $this->directories = $directories; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return array + */ + public function getDirectories() + { + return $this->directories; + } +} diff --git a/Configuration/BundleContainer.php b/Configuration/BundleContainer.php new file mode 100644 index 0000000..fa73e5d --- /dev/null +++ b/Configuration/BundleContainer.php @@ -0,0 +1,56 @@ + + */ +class BundleContainer +{ + /** + * @var array + */ + protected $bundles = array(); + + /** + * @param Bundle $bundle bundle + * + * @return BundleContainer + */ + public function add(Bundle $bundle) + { + $this->bundles[$bundle->getName()] = $bundle; + + return $this; + } + + /** + * @param string $ident ident + * + * @return Bundle|null + */ + public function get($ident) + { + return $this->has($ident) ? $this->bundles[$ident] : null; + } + + /** + * @param string $ident ident + * + * @return boolean + */ + public function has($ident) + { + return isset($this->bundles[$ident]); + } + + /** + * @return array + */ + public function all() + { + return $this->bundles; + } +} diff --git a/DependencyInjection/AtoumAtoumExtension.php b/DependencyInjection/AtoumAtoumExtension.php new file mode 100644 index 0000000..47069dc --- /dev/null +++ b/DependencyInjection/AtoumAtoumExtension.php @@ -0,0 +1,42 @@ + + */ +class AtoumAtoumExtension extends Extension +{ + /** + * {@inheritdoc} + */ + public function load(array $configs, ContainerBuilder $container) + { + $processor = new Processor(); + $configuration = new Configuration(); + + $config = $processor->processConfiguration($configuration, $configs); + + $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config/services')); + $loader->load('configuration.xml'); + + $container->setParameter('atoum.bundles', $config['bundles']); + } + + /** + * {@inheritdoc} + */ + public function getAlias() + { + return 'atoum'; + } +} diff --git a/DependencyInjection/Compiler/BundleDirectoriesResolverPass.php b/DependencyInjection/Compiler/BundleDirectoriesResolverPass.php new file mode 100644 index 0000000..c6e1220 --- /dev/null +++ b/DependencyInjection/Compiler/BundleDirectoriesResolverPass.php @@ -0,0 +1,43 @@ + + */ +class BundleDirectoriesResolverPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $bundles = $container->getParameter('kernel.bundles'); + $bundleContainer = $container->getDefinition('atoum.configuration.bundle.container'); + $configuration = $container->getParameterBag()->resolveValue($container->getParameter('atoum.bundles')); + + foreach ($configuration as $bundleName => $data) { + if (!isset($bundles[$bundleName])) { + throw new \LogicException(sprintf('Bundle "%s" does not exists.', $bundleName)); + } + + $rc = new \ReflectionClass($bundles[$bundleName]); + $directory = dirname($rc->getFileName()); + + $directories = array_map(function($v) use ($directory) { + return $directory.'/'.$v; + }, $data['directories']); + + $definition = new Definition( + $container->getParameter('atoum.configuration.bundle.class'), + array($bundleName, $directories) + ); + + $bundleContainer->addMethodCall('add', array($definition)); + } + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php new file mode 100644 index 0000000..f566713 --- /dev/null +++ b/DependencyInjection/Configuration.php @@ -0,0 +1,48 @@ + + */ +class Configuration implements ConfigurationInterface +{ + /** + * Generates the configuration tree builder. + * + * @return TreeBuilder The tree builder + */ + public function getConfigTreeBuilder() + { + $tb = new TreeBuilder(); + + return $tb + ->root('atoum_atoum') + ->children() + ->arrayNode('bundles') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->arrayNode('directories') + ->defaultValue(array( + 'Tests/Units', 'Tests/Controller', + )) + ->prototype('scalar') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + + return $tb; + } +} diff --git a/README.md b/README.md index 00f384e..a4ba49c 100644 --- a/README.md +++ b/README.md @@ -120,3 +120,32 @@ class BarController extends ControllerTest } } ``` + +## Command + +AtoumBundle is provided with a Symfony command. You can launch atoum tests on specific bundles. + +You have to define AtoumBundle on `AppKernel` + +```php +$bundles[] = new atoum\AtoumBundle\AtoumAtoumBundle(); +``` + +```shell +$ php app/console atoum FooBundle --env=test # launch tests of FooBundle +$ php app/console atoum FooBundle BarBundle --env=test # launch tests of FooBundle and BarBundle +$ php app/console atoum acme_foo --env=test # launch tests of bundle where alias is acme_foo +$ php app/console atoum --env=test # launch tests from configuration. +``` + +### Configuration + +Define your bundles on configuration: + +```yaml +atoum: + bundles: + FooBundle: ~ # FooBundle is defined with directories Tests/Units, Tests/Controller + BarBundle: + directories: [Tests/Units, Tests/Functional, ...] +``` diff --git a/Resources/config/services/configuration.xml b/Resources/config/services/configuration.xml new file mode 100644 index 0000000..c228409 --- /dev/null +++ b/Resources/config/services/configuration.xml @@ -0,0 +1,16 @@ + + + + + + atoum\AtoumBundle\Configuration\BundleContainer + atoum\AtoumBundle\Configuration\Bundle + + + + + + +