PhpSpec extension points

2,041 views

Published on

Published in: Business, Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,041
On SlideShare
0
From Embeds
0
Number of Embeds
109
Actions
Shares
0
Downloads
15
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

PhpSpec extension points

  1. 1. PhpSpec extension points for version 2.0.0
  2. 2. About me PHP Software engineer
 KrakDevs meetups organizer Huge fan of BDD/TDD 
 Part of Coduo 
 
 
 Web:
 https://github.com/norzechowicz
 https://twitter.com/norzechowicz
 http://coduo.pl
 http://krakdevs.pl Norbert Orzechowicz
  3. 3. This is everything you need. Trust me ;)
  4. 4. Ok, so how PhpSpec works?
  5. 5. Just like a regular Symfony2 console application Read more 
 http://symfony.com/doc/current/components/console/index.html
  6. 6. Ok, but what happens when user execute „run” command?
  7. 7. $ bin/phpspec run
  8. 8. #!/usr/bin/env php! <?php! //bin/phpspec! ! $app = new PhpSpecConsoleApplication(PHPSPEC_VERSION);!
  9. 9. Initialize console application <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! /**! * The command line application entry point! */! class Application extends BaseApplication! {! public function __construct($version)! {! }! }!
  10. 10. Create service container <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! /**! * The command line application entry point! */! class Application extends BaseApplication! {! public function __construct($version)! {! $this->container = new ServiceContainer;! parent::__construct('phpspec', $version);! }! }! In the name of dependency injection!
  11. 11. Service Container <?php! ///phpspec/src/PhpSpec/ServiceContainer.php! namespace PhpSpec;! ! class ServiceContainer! {! // Sets a object or a callback for the object creation. ! // A new object will be created every time! public function set($id, $value);! ! // Sets a object or a callback for the object creation. ! // The same object will be returned every time! public function setShared($id, $callable);! ! // Retrieves a service from the container! public function get($id);! ! // Retrieves a list of services of a given prefix! public function getByPrefix($prefix);! }! Explanation of the most important methods
  12. 12. Register service example <?php! ///phpspec/src/Acme/MyClass.php! namespace Acme;! ! class MyClass! {! public function setup(ServiceContainer $container)! {! $container->set('acme.service.foo', function ($c) {! return new Foo();! });! ! $container->setShared('acme.service.bar', function ($c) {! return new Bar();! });! ! $container->getByPrefix('acme.service');! // will return acme.service.foo as Foo incance & ! ! ! // acme.service.bar as Bar instance! }! }!
  13. 13. #!/usr/bin/env php! <?php! //bin/phpspec! ! $app = new PhpSpecConsoleApplication(PHPSPEC_VERSION);! $app->run();!
  14. 14. Run! <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! /**! * The command line application entry point! */! class Application extends BaseApplication! {! public function doRun(InputInterface $input, OutputInterface $output)! {! $this->setupContainer($this->container); ! }! }! Not so fast, setup service container first
  15. 15. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! }! }!
  16. 16. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! }! }!
  17. 17. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! }! }!
  18. 18. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! }! }!
  19. 19. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! $this->setupLocator($container);! }! }!
  20. 20. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! $this->setupLocator($container);! $this->setupLoader($container);! }! }!
  21. 21. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! $this->setupLocator($container);! $this->setupLoader($container);! $this->setupFormatter($container);! }! }!
  22. 22. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! $this->setupLocator($container);! $this->setupLoader($container);! $this->setupFormatter($container);! $this->setupRunner($container);! }! }!
  23. 23. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! $this->setupLocator($container);! $this->setupLoader($container);! $this->setupFormatter($container);! $this->setupRunner($container);! $this->setupCommands($container);! }! }!
  24. 24. <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! $this->setupLocator($container);! $this->setupLoader($container);! $this->setupFormatter($container);! $this->setupRunner($container);! $this->setupCommands($container);! ! $this->loadConfigurationFile($container);! }! }!
  25. 25. RUN! <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! public function doRun(InputInterface $input, OutputInterface $output)! {! $this->setupContainer($this->container);! ! foreach ($this->container->getByPrefix('console.commands') as $command) {! $this->add($command);! }! ! return parent::doRun($input, $output);! }! }! But first add commands. 
 By default „run” and „describe”.
  26. 26. Application is ready what now?
  27. 27. Run command <?php! //phpspec/src/PhpSpec/Console/Command/RunCommand.php! namespace PhpSpecConsoleCommand;! ! class RunCommand extends Command! {! protected function configure()! {! // configure input options, arguments, command name! }! ! protected function execute(InputInterface $input, OutputInterface $output)! {! // run suite with runner.suite service!! }! }! There is no magic here, just simple Symfony2 console command.
  28. 28. Suite you say?
  29. 29. Space where specifications exists Suite
  30. 30. Specifications?
  31. 31. Spaces where examples exists Suite FooClassSpec.php - Specification BarClassSpec.php - Specification FazClassSpec.php - Specification BazClassSpec.php - Specification
  32. 32. Examples!?
  33. 33. Yes, functions that describe object behavior (tests) Suite FooClassSpec.php - Specification function it_is_awesome() - Example function it_do_awesome_stuff() - Example function it_is_famous() - Example
  34. 34. Make sense now!
  35. 35. Run command simplified algorithm 1. Localize suite - Locator
 2. Load suite - Loader
 3. Run suite - Suite Runner
 4. Run specifications - Specification Runner
 5. Run examples - Example Runner
  36. 36. And what about extensions?
  37. 37. Remember container setup? <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupContainer(ServiceContainer $container)! {! // . . . ! $this->loadConfigurationFile($container);! }! }!
  38. 38. phpspec.yml suites: acme_suite: namespace: AcmeTheLib spec_prefix: acme_spec ! # shortcut for # my_suite: # namespace: TheNamespace my_suite: TheNamespace ! extensions:! - PhpSpecSymfony2ExtensionExtension
  39. 39. Extension interface <?php! //phpspec/src/PhpSpec/Extension/ExtensionInterface.php! namespace PhpSpecExtension;! ! use PhpSpecServiceContainer;! ! interface ExtensionInterface! {! /**! * @param ServiceContainer $container! */! public function load(ServiceContainer $container);! }!
  40. 40. That’s all?
  41. 41. Simply beautiful, right?
  42. 42. But what can I do with it?
  43. 43. But what can I do with it? Register event listeners as a services Replace existing services Register custom example maintainers Register new fomatters Register new code generators Replace suite locator Register new matchers Register new commands ! And many many more…
  44. 44. How?
  45. 45. Let me show you how to register an event listener.
  46. 46. Event subscriber class <?php! ///src/Coduo/PhpSpec/Listener/DataProviderListener.php! namespace CoduoPhpSpecListener;! ! class DataProviderListener implements EventSubscriberInterface! {! public static function getSubscribedEvents()! {! return array(! 'beforeSpecification' => array('beforeSpecification'),! );! }! ! public function beforeSpecification(SpecificationEvent $event)! {! // listener logic here ! }! }!
  47. 47. PhpSpec extension class <?php! //src/Coduo/PhpSpec/DataProviderExtension.php! namespace CoduoPhpSpec;! ! class DataProviderExtension implements ExtensionInterface! {! public function load(ServiceContainer $container)! {! $container->set(! 'event_dispatcher.listeners.data_provider', ! function ($c) {! return new DataProviderListener();! }! );! }! }!
  48. 48. And how PhpSpec know that my service is an event listener?
  49. 49. Just use proper prefix <?php! //phpspec/src/PhpSpec/Console/Application.php! ! use SymfonyComponentConsoleApplication as BaseApplication;! ! class Application extends BaseApplication! {! protected function setupEventDispatcher(ServiceContainer $container)! {! $container->setShared('event_dispatcher', function ($c) {! $dispatcher = new EventDispatcher;! ! array_map(! array($dispatcher, 'addSubscriber'),! $c->getByPrefix('event_dispatcher.listeners')! );! ! return $dispatcher;! });! }! }!
  50. 50. Are there any other prefixes that I can use?
  51. 51. List of prefixes that you can use by default. event_dispatcher.listeners - EventSubscriberInterfac
 code_generator.generators - GeneratorInterfac
 formatter.presenter.differ.engines - DifferEngineInterface
 locator.locators - ResourceLocatorInterface
 runner.maintaners - MaintainerInterface
 console.commands - Command
  52. 52. Thank you for your attention
  53. 53. Coduo 
 behaviour driven developers contact@coduo.pl Hire us!
  54. 54. Questions?

×