Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
ZürichPHP UG 18.06.2015

Pascal Thormeier
Setup
Big Symfony2 project for large Swiss
company

Multiple attached APIs

Tests in both PHPUnit and Behat/PhantomJS

Git...
ONCE UPON A TIME
History
Testing with manually created fixtures

Mocks had to be adjusted when APIs
changed

Using Guzzle's mock plugin

Sym...
Mocking:

• Do API call you would like to mock

• Copy/paste response to JSON/XML file

• Adjust to test cases

• Re-do who...
Behat tests couldn't really be mocked

Built an application that proxies API calls
and runs in the back in an own containe...
Switching to PHP-VCR

Behat testing and mocking became very
well possible

Old way of creating fixtures was no longer
neces...
WHAT ARE WE DOING
NOW?
Behat
Testing framework

Works with different so called drivers

Tests are written in Gherkin

We're using the Selenium2 an...
Selenium
PhantomJS as headless browser

PHP -> node.js -> PHP

... which leads to a problem
Selenium
Two different, independent PHP processes

Which fixture should the application load?
Selenium
Let's just use a cookie.
Selenium
<?php	
class AcmeContext extends MinkContext 	
{	
const COOKIE_NAME = 'BehatCassetteName';	
!
// ...	
!
public fu...
Selenium
<?php	
class AcmeContext extends MinkContext 	
{	
!
// ...	
!
public function getCasetteName($scope)	
{	
return '...
Gherkin
Feature: Some terse yet descriptive text of what is desired	
In order to realize a named business value	
As an exp...
Selenium
<?php	
// web/app_test.php - Remove this file while deployment!	
!
// ...	
!
// Execute standard SF2 stuff	
$kern...
Selenium
Neat side effects:

• Developing without internet!

• Change API responses for development
Minor pitfall:

• PhantomJS doesn't send this cookie when
doing AJAX

• Fixtures for AJAX would be named after the
URL, wh...
WebDriver
We want this in the SF WebDriver as well

Move it from app_test to AppKernel

Keep app_test.php as entry point f...
WebDriver
<?php	
class AppKernel extends Kernel	
{	
// ...	
public function handle(Request $request, ...)	
{	
if ('test' =...
WebDriver
Would only need minor adjustments to also
work in PHPUnit/Symfony WebTestCase
GitlabCI
CI is executing tests as well

Tests might not be mocked

Test will be mocked

Conflicts while making a new build
GitlabCI
<?php	
// ...	
!
if ($container->hasParameter('is_ci')) {	
VCR::configure()->setMode(VCR::MODE_NONE);	
}	
!
// ...
WRAP UP
Wrap up
PHP-VCR is awesome

But switching all fixtures to PHP-VCR might
be a lot of work

But you don't need to write them
...
Wrap up
Some pitfalls:

• Tests without fixtures

• Setup depending on framework might be difficult

• Not very transparent w...
Wrap up
Would highly recommend it because it
saves you a lot of time, work and nerves
Info
Info and documentation: http://php-
vcr.github.io

Source: https://github.com/php-vcr/php-vcr

VCR (ruby): https://gi...
Upcoming SlideShare
Loading in …5
×

PHP-VCR behat case study

16,475 views

Published on

A case study about the PHP-VCR: How it is used at a big Symfony2 project together with Behat/Selenium/PhantomJS and what kind of pitfalls exist and how to tackle them.

Published in: Technology

PHP-VCR behat case study

  1. 1. ZürichPHP UG 18.06.2015
 Pascal Thormeier
  2. 2. Setup Big Symfony2 project for large Swiss company Multiple attached APIs Tests in both PHPUnit and Behat/PhantomJS Gitlab CI and vagrant for development
  3. 3. ONCE UPON A TIME
  4. 4. History Testing with manually created fixtures Mocks had to be adjusted when APIs changed Using Guzzle's mock plugin Symfony's profiler helped out quite a lot...
  5. 5. Mocking: • Do API call you would like to mock • Copy/paste response to JSON/XML file • Adjust to test cases • Re-do whole fixture when small things changed History
  6. 6. Behat tests couldn't really be mocked Built an application that proxies API calls and runs in the back in an own container Loads of problems with that solution History
  7. 7. Switching to PHP-VCR Behat testing and mocking became very well possible Old way of creating fixtures was no longer necessary History
  8. 8. WHAT ARE WE DOING NOW?
  9. 9. Behat Testing framework Works with different so called drivers Tests are written in Gherkin We're using the Selenium2 and Symfony Web drivers
  10. 10. Selenium PhantomJS as headless browser PHP -> node.js -> PHP ... which leads to a problem
  11. 11. Selenium Two different, independent PHP processes Which fixture should the application load?
  12. 12. Selenium Let's just use a cookie.
  13. 13. Selenium <?php class AcmeContext extends MinkContext { const COOKIE_NAME = 'BehatCassetteName'; ! // ... ! public function before(BeforeScenarioScope $scope) { $this->getSession()->setCookie( self::COOKIE_NAME, $this->getCassetteName($scope) ); } ! // ... ! }
  14. 14. Selenium <?php class AcmeContext extends MinkContext { ! // ... ! public function getCasetteName($scope) { return 'fixtures/' . self::normalize($scope->getFeature()->getTitle()) . '/' . self::normalize($scope->getScenario()->getTitle()) ; } ! public static function normalize($string) { return trim(preg_replace( '/[^a-zA-Z0-9]+/', '_', $string ), '_'); } ! // ... ! }
  15. 15. Gherkin Feature: Some terse yet descriptive text of what is desired In order to realize a named business value As an explicit system actor I want to gain some beneficial outcome which furthers the goal ! Additional text... ! Scenario: Some determinable business situation Given some precondition And some other precondition When some action by the actor And some other action And yet another action Then some testable outcome is achieved And something else we can check happens too ! Scenario: A different situation ...
  16. 16. Selenium <?php // web/app_test.php - Remove this file while deployment! ! // ... ! // Execute standard SF2 stuff $kernel = new AppKernel('test', true); $kernel->loadClassCache(); Request::enableHttpMethodParameterOverride(); $request = Request::createFromGlobals(); ! // Set up VCR with fixture name from cookie $fixture = $request->cookies->get(AcmeContext::COOKIE_NAME, null); if (!$fixture) { $fixture = AcmeContext::normalize($request->getUri()); } VCR::turnOn(); VCR::insertCassette('../tests/' . $fixture . '.json'); ! // Execute standard SF2 stuff $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response); ! // Save the fixture VCR::eject(); VCR::turnOff();
  17. 17. Selenium Neat side effects: • Developing without internet! • Change API responses for development
  18. 18. Minor pitfall: • PhantomJS doesn't send this cookie when doing AJAX • Fixtures for AJAX would be named after the URL, which works but isn't as nice • You have to set the cookie manually in JS again Selenium
  19. 19. WebDriver We want this in the SF WebDriver as well Move it from app_test to AppKernel Keep app_test.php as entry point for PhantomJS
  20. 20. WebDriver <?php class AppKernel extends Kernel { // ... public function handle(Request $request, ...) { if ('test' === $this->getEnvironment()) { $fixture = $request->cookies->get( AcmeContext::COOKIE_NAME, null ); ! if (!$fixture) { $fixture = AcmeContext::normalize( $request->getUri() ); } ! VCR::turnOn(); VCR::insertCassette('../tests/' . $fixture . '.json'); } ! return parent::handle($request, ...); } // ... }
  21. 21. WebDriver Would only need minor adjustments to also work in PHPUnit/Symfony WebTestCase
  22. 22. GitlabCI CI is executing tests as well Tests might not be mocked Test will be mocked Conflicts while making a new build
  23. 23. GitlabCI <?php // ... ! if ($container->hasParameter('is_ci')) { VCR::configure()->setMode(VCR::MODE_NONE); } ! // ...
  24. 24. WRAP UP
  25. 25. Wrap up PHP-VCR is awesome But switching all fixtures to PHP-VCR might be a lot of work But you don't need to write them yourselves anymore
  26. 26. Wrap up Some pitfalls: • Tests without fixtures • Setup depending on framework might be difficult • Not very transparent where data comes from inside tests • First test run to write all the fixtures is slow
  27. 27. Wrap up Would highly recommend it because it saves you a lot of time, work and nerves
  28. 28. Info Info and documentation: http://php- vcr.github.io Source: https://github.com/php-vcr/php-vcr VCR (ruby): https://github.com/vcr/vcr Follow: @pthormeier and @adrian_philipp

×