Behat internals for advanced usage. Symfony Camp 2016

45
Serhii Polishchuk spolishchuk[at]oroinc.com Behat Internals for advanced usage

Transcript of Behat internals for advanced usage. Symfony Camp 2016

Page 1: Behat internals for advanced usage. Symfony Camp 2016

Serhii Polishchukspolishchuk[at]oroinc.com

Behat Internalsfor advanced usage

Page 2: Behat internals for advanced usage. Symfony Camp 2016

Behat Internals for advanced usage

What I'm tolking aboutTale of contents

● Part1. BDD. Common understanding● Part2. Behat. Inside Out● Part3. Behat+Oro. UI tests implementation

Page 3: Behat internals for advanced usage. Symfony Camp 2016

Behat Internals for advanced usage

BDD. Common understandingUnderstanding is deeper than knowledge

● TLD. TDD. BDD.● Two Common Issues.● Who know everything about bugs?● Most wrong thing that ever happen in BDD.● Introducing Gherkin

Page 4: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

TLD. TDD.Write tests before of fafter code?

http://compilehorrors.com/test-driven-development-tdd-vs-test-last-development-tld-a-comparative-study/

● Time required● Learning curve● Code Size● Tests stability

Page 5: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

BDD.You might don't understand code of library, but you should understand the Behavior

Page 6: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Two Common IssuesIn a any kind of project

1. Building software right2. Building right software

Page 7: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Building software right

● Design Patterns● SOLID● Tests● Continuous Integration● Deploy● Semantic Versioning

Page 8: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Building right software

John Ferguson Smart. BDD In action

“According to the Standish Group’s CHAOS studies, on average some 45% of the features delivered into production are never used.”

Page 9: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Building right software

Page 10: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Who know everything about bugs?

Page 11: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Who know everything about bugs?QA know what bugs will happen before developing will finished

Page 12: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Finally we are all togetherBI, QA and developer can understand each other better, using one unified language

Page 13: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

The most wrong thing that ever happen in BDDBecause it made it usable.

10 years of Doing Behaviour-Driven Development All Wrong (part 1) by Liz Keogh https://youtu.be/2EM4itu7j7I

Page 14: Behat internals for advanced usage. Symfony Camp 2016

BDD. Common understanding

Introducing GherkinThe lenguage that we can use to discuss of behavior of your system

Cucumber reference https://cucumber.io/docs/reference

Feature: Refund item

Scenario: Jeff returns a faulty microwave

Given Jeff has bought a microwave for $100

And he has a receipt

When he returns the microwave

Then Jeff should be refunded $100

Page 15: Behat internals for advanced usage. Symfony Camp 2016

Behat Internals for advanced usage

Behat. Inside Out

● PHP callback matching● From Console to Browser● Behat as symfony console application● Behat Configuration● Behat Extensions● Behat Controllers● Event Dispatching● Context Initializers

Page 16: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

PHP callback matchingEvery feature step matched to php callback

Page 17: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

From Console to Browser

Page 18: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat as symfony console applicationWith single command

● Create DI Container and process configuration through Extensions● Create behat command and add to application● Command run Controllers in selected order● Controller can return integer status for interrupt execution● ExerciseController collect features and test its

Page 19: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Extensionsnamespace Behat\Testwork\ServiceContainer;

interface Extension extends CompilerPassInterface{ public function getConfigKey();

public function initialize(ExtensionManager $extensionManager);

public function configure(ArrayNodeDefinition $builder);

public function load(ContainerBuilder $container, array $config);}

namespace Symfony\Component\DependencyInjection\Compiler;

interface CompilerPassInterface{ public function process(ContainerBuilder $container);}

Page 20: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Extensions

● EnvironmentExtension● GherkinExtension● OutputExtension● TranslatorExtension● ContextExtension● SnippetExtension● MinkExtension● Symfony2Extension● OroTestFrameworkExtension

https://git.io/vXIXC OroTestFrameworkExtension

Page 21: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Configuration

bin/behat --config-reference Display the configuration reference

default: &default extensions: Behat\MinkExtension: base_url: 'http://localhost.com/' default_session: 'first_session' sessions: second_session: oroSelenium2: wd_host: "http://localhost:8643/wd/hub" first_session: oroSelenium2: wd_host: "http://localhost:8643/wd/hub" Behat\Symfony2Extension: kernel: env: 'prod' debug: false context: path_suffix: 'Tests/Behat/Features' class_suffix: 'Tests\Behat\Context\FeatureContext' Oro\Bundle\TestFrameworkBundle\Behat\ServiceContainer\OroTestFrameworkExtension: shared_contexts: - Oro\Bundle\TestFrameworkBundle\Tests\Behat\Context\OroMainContext - Oro\Bundle\TestFrameworkBundle\Tests\Behat\Context\FixturesContext - Oro\Bundle\ActivityListBundle\Tests\Behat\Context\ActivityContext - Oro\Bundle\DataGridBundle\Tests\Behat\Context\GridContext - Oro\Bundle\SecurityBundle\Tests\Behat\Context\ACLContext suites: []

selenium2: <<: *default extensions: Behat\MinkExtension: sessions: second_session: oroSelenium2: wd_host: 'http://localhost:4444/wd/hub' first_session: oroSelenium2: wd_host: 'http://localhost:4444/wd/hub'

Page 22: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Controllersnamespace Behat\Testwork\Cli;

final class Command extends \Symfony\Component\Console\Command\Command{ private $controllers = array();

public function __construct($commandName, array $controllers) { $this->controllers = $controllers;

parent::__construct($commandName); }

protected function configure() { foreach ($this->controllers as $controller) { $controller->configure($this); } }

protected function execute(InputInterface $input, OutputInterface $output) { foreach ($this->controllers as $controller) { if (is_int($return = $controller->execute($input, $output))) { return $return; } }

return 0; }}

Page 23: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Controllers

namespace Behat\Testwork\Cli;

interface Controller{ public function configure(SymfonyCommand $command);

public function execute(InputInterface $input, OutputInterface $output);}

cli.controller.mesure_execution_time: class: Oro\Bundle\TestFrameworkBundle\Behat\Cli\MeasureExecutionTimeController arguments: - '@oro_test.listener.step_duration_measure_subscriber' - '@event_dispatcher' tags: - { name: 'cli.controller', priority: 1100 }

Behat Controller Definition

Page 24: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Controllersclass AvailableSuitesController implements Controller{ private $suiteRepository;

public function __construct(SuiteRepository $suiteRepository) { $this->suiteRepository = $suiteRepository; }

public function configure(SymfonyCommand $command) { $command ->addOption( '--available-suites', null, InputOption::VALUE_NONE, 'Show all available test suites.'.PHP_EOL. 'Suites can be configured automatically by extensions, and manually by configuration' ); }

public function execute(InputInterface $input, OutputInterface $output) { if (false === $input->getOption('available-suites')) { return; }

foreach ($this->suiteRepository->getSuites() as $suite) { $output->writeln($suite->getName()); }

return 0; }}

Page 25: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Behat Controllers

● ExerciseController● RerunController● OrderController● AvailableDefinitionsController● FilterController● InitializationController● OutputController● LanguageController● VerbosityController● MeasureExecutionTimeController

Page 26: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Event Dispatching

Page 27: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Context InitializersModify context in runtime

namespace Behat\Behat\Context\Initializer;

interface ContextInitializer{ public function initializeContext(Context $context);}

Page 28: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Context InitializersModify context in runtime

namespace Oro\Bundle\TestFrameworkBundle\Behat\Context\Initializer;

class FixtureLoaderInitializer implements ContextInitializer{ protected $fixtureLoader;

public function __construct(FixtureLoader $fixtureLoader) { $this->fixtureLoader = $fixtureLoader; }

public function initializeContext(Context $context) { if ($context instanceof FixtureLoaderAwareInterface) { $context->setFixtureLoader($this->fixtureLoader); } }}

Page 29: Behat internals for advanced usage. Symfony Camp 2016

Behat. Inside Out

Context InitializersModify context in runtime

oro_behat_fixture_loader_initializer: class: Oro\Bundle\TestFrameworkBundle\Behat\Context\Initializer\FixtureLoaderInitializer arguments: - '@oro_test.context.fixture_loader' tags: - { name: 'context.initializer' }

Page 30: Behat internals for advanced usage. Symfony Camp 2016

Behat Internals for advanced usage

Behat+Oro. UI tests implementation

● Gherkin syntax. Hunt the value● Gherkin syntax. Scenario definition● Gherkin syntax. Examples● Gherkin syntax. Tables● ACL● Elements. What is element● Elements. Describing element● Pages● Inline fixtures● Alice fixtures● Performance● Tests stability

Page 31: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Gherkin syntaxHunt the value

Page 32: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Gherkin syntaxScenario definition

Page 33: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Gherkin syntaxExamples

Page 34: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Gherkin syntaxTables

Page 35: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

ACLSeveral users in one scenario

Page 36: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

ElementsWhat is element

Page 37: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

ElementsDescribing element

Page 38: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Pages

For CRUD pages:● Index page - for list entities with grid● Create page - for page with empty form● Edit page - needs entity title for open● View page - needs entity title for open

Other pages can have any other name

Page 39: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Inline fixturesWrite fixtures right in scenarios

Page 40: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Inline fixturesWrite fixtures right in scenarios

Page 41: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Alice fixturesWrite complicated fixtures with dependencies in yml files

https://github.com/nelmio/alice

Page 42: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Performanceapplication load + selenium ≈ 90% of test time

Page 43: Behat internals for advanced usage. Symfony Camp 2016

Behat+Oro. UI tests implementation

Tests stability

Page 44: Behat internals for advanced usage. Symfony Camp 2016

Behat Internals for advanced usage

Q/A

Page 45: Behat internals for advanced usage. Symfony Camp 2016

Behat Internals for advanced usage

REFERENCES

● 10 years of Doing Behaviour-Driven Development All Wrong by Liz Keogh https://www.youtube.com/watch?v=2EM4itu7j7I

● Bdd in action by John Ferguson Smart https://www.manning.com/books/bdd-in-action ● Interview with Dan North on Behavior-Driven Development

https://www.youtube.com/watch?v=qWsnmx45734 ● About BDD at Liz Keogh official site https://lizkeogh.com/behaviour-driven-development/ ● Cucumber reference https://cucumber.io/docs/reference ● http://blog.standishgroup.com/ ● Behat in Oro https://github.com/orocrm/platform/tree/master/src/Oro/Bundle/TestFrameworkBundle/Behat ● Behat - A php framework for autotesting your business expectations. http://behat.org/en/latest/