PhpSpec extension points

56
PhpSpec extension points for version 2.0.0

Transcript of PhpSpec extension points

Page 1: PhpSpec extension points

PhpSpec extension pointsfor version 2.0.0

Page 2: PhpSpec extension points

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.plhttp://krakdevs.plNorbert Orzechowicz

Page 3: PhpSpec extension points
Page 4: PhpSpec extension points
Page 5: PhpSpec extension points

This is everything you need. Trust me ;)

Page 6: PhpSpec extension points

Ok, so how PhpSpec works?

Page 7: PhpSpec extension points

Just like a regular Symfony2 console

application

Read more http://symfony.com/doc/current/components/console/index.html

Page 8: PhpSpec extension points

Ok, but what happens when user execute „run”

command?

Page 9: PhpSpec extension points

$ bin/phpspec run

Page 10: PhpSpec extension points

#!/usr/bin/env php!<?php!//bin/phpspec!!$app = new PhpSpec\Console\Application(PHPSPEC_VERSION);!

Page 11: PhpSpec extension points

Initialize console application<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application as BaseApplication;!!/**! * The command line application entry point! */!class Application extends BaseApplication!{! public function __construct($version)! {! }!}!

Page 12: PhpSpec extension points

Create service container<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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!

Page 13: PhpSpec extension points

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

Page 14: PhpSpec extension points

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! }!}!

Page 15: PhpSpec extension points

#!/usr/bin/env php!<?php!//bin/phpspec!!$app = new PhpSpec\Console\Application(PHPSPEC_VERSION);!$app->run();!

Page 16: PhpSpec extension points

Run! <?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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

Page 17: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application as BaseApplication;!!class Application extends BaseApplication!{! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! }!}!

Page 18: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application as BaseApplication;!!class Application extends BaseApplication!{! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! }!}!

Page 19: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application as BaseApplication;!!class Application extends BaseApplication!{! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! }!}!

Page 20: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application as BaseApplication;!!class Application extends BaseApplication!{! protected function setupContainer(ServiceContainer $container)! {! $this->setupIO($container);! $this->setupEventDispatcher($container);! $this->setupGenerators($container);! $this->setupPresenter($container);! }!}!

Page 21: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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);! }!}!

Page 22: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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);! }!}!

Page 23: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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);! }!}!

Page 24: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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);! }!}!

Page 25: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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);! }!}!

Page 26: PhpSpec extension points

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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);! }!}!

Page 27: PhpSpec extension points

RUN!

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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”.

Page 28: PhpSpec extension points

Application is ready what now?

Page 29: PhpSpec extension points

Run command

<?php!//phpspec/src/PhpSpec/Console/Command/RunCommand.php!namespace PhpSpec\Console\Command;!!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.

Page 30: PhpSpec extension points

Suite you say?

Page 31: PhpSpec extension points

Space where specifications exists

Suite

Page 32: PhpSpec extension points

Specifications?

Page 33: PhpSpec extension points

Spaces where examples exists

Suite

FooClassSpec.php - Specification

BarClassSpec.php - Specification

FazClassSpec.php - Specification

BazClassSpec.php - Specification

Page 34: PhpSpec extension points

Examples!?

Page 35: PhpSpec extension points

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

Page 36: PhpSpec extension points

Make sense now!

Page 37: PhpSpec extension points

Run command simplified algorithm

1. Localize suite - Locator 2. Load suite - Loader 3. Run suite - Suite Runner 4. Run specifications - Specification Runner5. Run examples - Example Runner

Page 38: PhpSpec extension points

And what about extensions?

Page 39: PhpSpec extension points

Remember container setup?

<?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application as BaseApplication;!!class Application extends BaseApplication!{! protected function setupContainer(ServiceContainer $container)! {! // . . . ! $this->loadConfigurationFile($container);! }!}!

Page 40: PhpSpec extension points

phpspec.yml suites: acme_suite: namespace: Acme\TheLib spec_prefix: acme_spec ! # shortcut for # my_suite: # namespace: The\Namespace my_suite: The\Namespace !extensions:! - PhpSpec\Symfony2Extension\Extension

Page 41: PhpSpec extension points

Extension interface<?php!//phpspec/src/PhpSpec/Extension/ExtensionInterface.php!namespace PhpSpec\Extension;!!use PhpSpec\ServiceContainer;!!interface ExtensionInterface!{! /**! * @param ServiceContainer $container! */! public function load(ServiceContainer $container);!}!

Page 42: PhpSpec extension points

That’s all?

Page 43: PhpSpec extension points

Simply beautiful, right?

Page 44: PhpSpec extension points

But what can I do with it?

Page 45: PhpSpec extension points

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…

Page 46: PhpSpec extension points

How?

Page 47: PhpSpec extension points

Let me show you how to register an event listener.

Page 48: PhpSpec extension points

Event subscriber class<?php!///src/Coduo/PhpSpec/Listener/DataProviderListener.php!namespace Coduo\PhpSpec\Listener;!!class DataProviderListener implements EventSubscriberInterface!{! public static function getSubscribedEvents()! {! return array(! 'beforeSpecification' => array('beforeSpecification'),! );! }!! public function beforeSpecification(SpecificationEvent $event)! {! // listener logic here ! }!}!

Page 49: PhpSpec extension points

PhpSpec extension class<?php!//src/Coduo/PhpSpec/DataProviderExtension.php!namespace Coduo\PhpSpec;!!class DataProviderExtension implements ExtensionInterface!{! public function load(ServiceContainer $container)! {! $container->set(! 'event_dispatcher.listeners.data_provider', ! function ($c) {! return new DataProviderListener();! }! );! }!}!

Page 50: PhpSpec extension points

And how PhpSpec know that my service is an

event listener?

Page 51: PhpSpec extension points

Just use proper prefix <?php!//phpspec/src/PhpSpec/Console/Application.php!!use Symfony\Component\Console\Application 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;! });! }!}!

Page 52: PhpSpec extension points

Are there any other prefixes that I can use?

Page 53: PhpSpec extension points

List of prefixes that you can use by default.

event_dispatcher.listeners - EventSubscriberInterfac code_generator.generators - GeneratorInterfac formatter.presenter.differ.engines - Differ\EngineInterface locator.locators - ResourceLocatorInterface runner.maintaners - MaintainerInterface console.commands - Command

Page 54: PhpSpec extension points

Thank you for your attention

Page 55: PhpSpec extension points

Coduo behaviour driven developers

[email protected]

Hire us!

Page 56: PhpSpec extension points

Questions?