From b42fa843de9685454d29714a0af256b3ee27b6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20PY?= Date: Tue, 8 Jan 2013 22:35:54 +0100 Subject: [PATCH 1/3] Launch tests for 1,n bundles, using bundle name or alias extension. --- Command/AtoumCommand.php | 88 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Command/AtoumCommand.php diff --git a/Command/AtoumCommand.php b/Command/AtoumCommand.php new file mode 100644 index 0000000..74fcc09 --- /dev/null +++ b/Command/AtoumCommand.php @@ -0,0 +1,88 @@ + + */ +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 ... +EOF + ) + ->addArgument('bundles', InputArgument::IS_ARRAY, 'Launch tests of these bundles.') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $runner = new runner('atoum'); + + foreach ($input->getArgument('bundles') as $name) { + $bundle = $this->extractBundleFromKernel($name); + + $runner->addTestAllDirectory(sprintf('%s/Tests/Units', $bundle->getPath())); + } + + $runner->run(array( + '--test-all' + )); + } + + /** + * @param string $name name + * + * @return Bundle + */ + protected function extractBundleFromKernel($name) + { + $bundles = $this->getContainer()->get('kernel')->getBundles(); + + if (preg_match('/Bundle$/', $name)) { + if (!isset($bundles[$name])) { + throw new \LogicException(sprintf('Bundle "%s" does not exists or is not activated.', $name)); + } + + return $bundles[$name]; + } else { + foreach ($bundles as $bundle) { + $extension = $bundle->getContainerExtension(); + + if ($extension && $extension->getAlias() == $name) { + return $bundle; + } + } + + throw new \LogicException(sprintf('Bundle with alias "%s" does not exists or is not activated.', $name)); + } + } +} From b163e7b85a0d43e0b9b9fdd811bcac174698add9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20PY?= Date: Mon, 14 Jan 2013 23:23:46 +0100 Subject: [PATCH 2/3] Define Configuration by Bundle. --- AtoumAtoumBundle.php | 30 +++++++ Command/AtoumCommand.php | 78 +++++++++++++++---- Configuration/Bundle.php | 47 +++++++++++ Configuration/BundleContainer.php | 56 +++++++++++++ DependencyInjection/AtoumAtoumExtension.php | 42 ++++++++++ .../BundleDirectoriesResolverPass.php | 43 ++++++++++ DependencyInjection/Configuration.php | 48 ++++++++++++ Resources/config/services/configuration.xml | 16 ++++ 8 files changed, 345 insertions(+), 15 deletions(-) create mode 100644 Configuration/Bundle.php create mode 100644 Configuration/BundleContainer.php create mode 100644 DependencyInjection/AtoumAtoumExtension.php create mode 100644 DependencyInjection/Compiler/BundleDirectoriesResolverPass.php create mode 100644 DependencyInjection/Configuration.php create mode 100644 Resources/config/services/configuration.xml 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/Command/AtoumCommand.php b/Command/AtoumCommand.php index 74fcc09..0fac4da 100644 --- a/Command/AtoumCommand.php +++ b/Command/AtoumCommand.php @@ -8,6 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\HttpKernel\Bundle\Bundle; +use atoum\AtoumBundle\Configuration\Bundle as BundleConfiguration; use mageekguy\atoum\scripts\runner; /** @@ -47,42 +48,89 @@ protected function execute(InputInterface $input, OutputInterface $output) { $runner = new runner('atoum'); - foreach ($input->getArgument('bundles') as $name) { - $bundle = $this->extractBundleFromKernel($name); + $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())); + } - $runner->addTestAllDirectory(sprintf('%s/Tests/Units', $bundle->getPath())); + foreach ($directories as $directory) { + $runner->addTestAllDirectory($directory); + } } - $runner->run(array( - '--test-all' - )); + if (count($runner->getTestAllDirectories()) == 0) { + $output->writeln('There is no test to launch.'); + } else { + $runner->run(array( + '--test-all' + )); + } } /** * @param string $name name * - * @return Bundle + * @return BundleConfiguration */ - protected function extractBundleFromKernel($name) + public function extractBundleConfigurationFromKernel($name) { - $bundles = $this->getContainer()->get('kernel')->getBundles(); + $kernelBundles = $this->getContainer()->get('kernel')->getBundles(); + $bundle = null; if (preg_match('/Bundle$/', $name)) { - if (!isset($bundles[$name])) { + if (!isset($kernelBundles[$name])) { throw new \LogicException(sprintf('Bundle "%s" does not exists or is not activated.', $name)); } - return $bundles[$name]; + $bundle = $kernelBundles[$name]; } else { - foreach ($bundles as $bundle) { - $extension = $bundle->getContainerExtension(); + foreach ($kernelBundles as $kernelBundle) { + $extension = $kernelBundle->getContainerExtension(); if ($extension && $extension->getAlias() == $name) { - return $bundle; + $bundle = $kernelBundle; + break; } } - throw new \LogicException(sprintf('Bundle with alias "%s" does not exists or is not activated.', $name)); + 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/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 + + + + + + + From 66dec4c0e3e376fcd79e6059f3a41da398b71b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20PY?= Date: Tue, 15 Jan 2013 00:00:53 +0100 Subject: [PATCH 3/3] Improve documentation, edit CHANGELOG. --- CHANGELOG.md | 3 ++- Command/AtoumCommand.php | 5 +++++ README.md | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f58958..a9c620c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ * master (next 1.1.0) + * Add command to launch tests on bundles. * Add fluent interface for controllers testing * Compatibility break (static $kernel variable become a class variable) * 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 index 0fac4da..a791819 100644 --- a/Command/AtoumCommand.php +++ b/Command/AtoumCommand.php @@ -35,6 +35,11 @@ protected function configure() 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.') diff --git a/README.md b/README.md index 5068000..9fc4f81 100644 --- a/README.md +++ b/README.md @@ -110,3 +110,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, ...] +```