SlideShare a Scribd company logo
1 of 28
Download to read offline
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

Gitlab CI and vagrant for development
ONCE UPON A TIME
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...
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
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
Switching to PHP-VCR

Behat testing and mocking became very
well possible

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

Works with different so called drivers

Tests are written in Gherkin

We're using the Selenium2 and Symfony
Web drivers
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 function before(BeforeScenarioScope $scope)	
{	
$this->getSession()->setCookie(	
self::COOKIE_NAME,	
$this->getCassetteName($scope)	
);	
}	
!
// ...	
!
}
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	
), '_');	
}	
!
// ...	
!
}
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	
...
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();
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, which works but isn't as nice

• You have to set the cookie manually in JS again
Selenium
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
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, ...);	
}	
// ...	
}
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
yourselves anymore
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
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://github.com/vcr/vcr

Follow: @pthormeier and @adrian_philipp

More Related Content

What's hot

Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Puppet
 
CodeIgniter Ant Scripting
CodeIgniter Ant ScriptingCodeIgniter Ant Scripting
CodeIgniter Ant ScriptingAlbert Rosa
 
Code igniter unittest-part1
Code igniter unittest-part1Code igniter unittest-part1
Code igniter unittest-part1Albert Rosa
 
Flask With Server-Sent Event
Flask With Server-Sent EventFlask With Server-Sent Event
Flask With Server-Sent EventTencent
 
Futureproof angular 1.x applications - yannick houbrix
Futureproof angular 1.x  applications - yannick houbrixFutureproof angular 1.x  applications - yannick houbrix
Futureproof angular 1.x applications - yannick houbrixAxxes IT Consultancy
 
Managing Complexity with Module::Release
Managing Complexity with Module::ReleaseManaging Complexity with Module::Release
Managing Complexity with Module::Releasebrian d foy
 
Implement server push in flask framework
Implement server push in flask frameworkImplement server push in flask framework
Implement server push in flask frameworkChi-Chia Huang
 
Pitfalls in Performance Testing AxxesCC 06/2015
Pitfalls in Performance Testing AxxesCC 06/2015Pitfalls in Performance Testing AxxesCC 06/2015
Pitfalls in Performance Testing AxxesCC 06/2015Axxes IT Consultancy
 
Vagrant - the essence of DevOps in a tool
Vagrant - the essence of DevOps in a toolVagrant - the essence of DevOps in a tool
Vagrant - the essence of DevOps in a toolPaul Stack
 
GTLAB Overview
GTLAB OverviewGTLAB Overview
GTLAB Overviewmarpierc
 
Full stack, Full run, Full test
Full stack, Full run, Full testFull stack, Full run, Full test
Full stack, Full run, Full testTaras Slipets
 
Intro to testing Javascript with jasmine
Intro to testing Javascript with jasmineIntro to testing Javascript with jasmine
Intro to testing Javascript with jasmineTimothy Oxley
 
Introducing Revel
Introducing RevelIntroducing Revel
Introducing RevelZhebr
 
Continuous integration with Git & CI Joe
Continuous integration with Git & CI JoeContinuous integration with Git & CI Joe
Continuous integration with Git & CI JoeShawn Price
 
Unit Testing with Jest
Unit Testing with JestUnit Testing with Jest
Unit Testing with JestMaayan Glikser
 
Server::Starter meets Java
Server::Starter meets JavaServer::Starter meets Java
Server::Starter meets JavaTokuhiro Matsuno
 

What's hot (20)

Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
 
CodeIgniter Ant Scripting
CodeIgniter Ant ScriptingCodeIgniter Ant Scripting
CodeIgniter Ant Scripting
 
Code igniter unittest-part1
Code igniter unittest-part1Code igniter unittest-part1
Code igniter unittest-part1
 
Flask With Server-Sent Event
Flask With Server-Sent EventFlask With Server-Sent Event
Flask With Server-Sent Event
 
Ava unit test
Ava unit testAva unit test
Ava unit test
 
Cramp websockets
Cramp websocketsCramp websockets
Cramp websockets
 
Futureproof angular 1.x applications - yannick houbrix
Futureproof angular 1.x  applications - yannick houbrixFutureproof angular 1.x  applications - yannick houbrix
Futureproof angular 1.x applications - yannick houbrix
 
Managing Complexity with Module::Release
Managing Complexity with Module::ReleaseManaging Complexity with Module::Release
Managing Complexity with Module::Release
 
Implement server push in flask framework
Implement server push in flask frameworkImplement server push in flask framework
Implement server push in flask framework
 
C++ Production Debugging
C++ Production DebuggingC++ Production Debugging
C++ Production Debugging
 
Pitfalls in Performance Testing AxxesCC 06/2015
Pitfalls in Performance Testing AxxesCC 06/2015Pitfalls in Performance Testing AxxesCC 06/2015
Pitfalls in Performance Testing AxxesCC 06/2015
 
Vagrant - the essence of DevOps in a tool
Vagrant - the essence of DevOps in a toolVagrant - the essence of DevOps in a tool
Vagrant - the essence of DevOps in a tool
 
Capistrano
CapistranoCapistrano
Capistrano
 
GTLAB Overview
GTLAB OverviewGTLAB Overview
GTLAB Overview
 
Full stack, Full run, Full test
Full stack, Full run, Full testFull stack, Full run, Full test
Full stack, Full run, Full test
 
Intro to testing Javascript with jasmine
Intro to testing Javascript with jasmineIntro to testing Javascript with jasmine
Intro to testing Javascript with jasmine
 
Introducing Revel
Introducing RevelIntroducing Revel
Introducing Revel
 
Continuous integration with Git & CI Joe
Continuous integration with Git & CI JoeContinuous integration with Git & CI Joe
Continuous integration with Git & CI Joe
 
Unit Testing with Jest
Unit Testing with JestUnit Testing with Jest
Unit Testing with Jest
 
Server::Starter meets Java
Server::Starter meets JavaServer::Starter meets Java
Server::Starter meets Java
 

Similar to PHP-VCR behat case study

Continous Delivering a PHP application
Continous Delivering a PHP applicationContinous Delivering a PHP application
Continous Delivering a PHP applicationJavier López
 
One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.Javier López
 
Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.catPablo Godel
 
Altitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly WorkshopAltitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly WorkshopFastly
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesPavol Pitoňák
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidenceJohn Congdon
 
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Ondřej Machulda
 
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav DukhinFwdays
 
Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIBruno Rocha
 
Monitoring kubernetes with prometheus
Monitoring kubernetes with prometheusMonitoring kubernetes with prometheus
Monitoring kubernetes with prometheusBrice Fernandes
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introductionNir Kaufman
 
Getting started with puppet and vagrant (1)
Getting started with puppet and vagrant (1)Getting started with puppet and vagrant (1)
Getting started with puppet and vagrant (1)Puppet
 
Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)HungWei Chiu
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Ryan Weaver
 
Javascript tdd byandreapaciolla
Javascript tdd byandreapaciollaJavascript tdd byandreapaciolla
Javascript tdd byandreapaciollaAndrea Paciolla
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationCiaranMcNulty
 
Learn basic ansible using docker
Learn basic ansible using dockerLearn basic ansible using docker
Learn basic ansible using dockerLarry Cai
 
Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?Tobias Schneck
 
Symfony finally swiped right on envvars
Symfony finally swiped right on envvarsSymfony finally swiped right on envvars
Symfony finally swiped right on envvarsSam Marley-Jarrett
 

Similar to PHP-VCR behat case study (20)

Continous Delivering a PHP application
Continous Delivering a PHP applicationContinous Delivering a PHP application
Continous Delivering a PHP application
 
One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.
 
Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.cat
 
Altitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly WorkshopAltitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly Workshop
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile Devices
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
 
Mcollective introduction
Mcollective introductionMcollective introduction
Mcollective introduction
 
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
 
Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CI
 
Monitoring kubernetes with prometheus
Monitoring kubernetes with prometheusMonitoring kubernetes with prometheus
Monitoring kubernetes with prometheus
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 
Getting started with puppet and vagrant (1)
Getting started with puppet and vagrant (1)Getting started with puppet and vagrant (1)
Getting started with puppet and vagrant (1)
 
Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
 
Javascript tdd byandreapaciolla
Javascript tdd byandreapaciollaJavascript tdd byandreapaciolla
Javascript tdd byandreapaciolla
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless Integration
 
Learn basic ansible using docker
Learn basic ansible using dockerLearn basic ansible using docker
Learn basic ansible using docker
 
Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?
 
Symfony finally swiped right on envvars
Symfony finally swiped right on envvarsSymfony finally swiped right on envvars
Symfony finally swiped right on envvars
 

Recently uploaded

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 

Recently uploaded (20)

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 

PHP-VCR behat case study

  • 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. ONCE UPON A TIME
  • 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. 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. 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. Switching to PHP-VCR Behat testing and mocking became very well possible Old way of creating fixtures was no longer necessary History
  • 8. WHAT ARE WE DOING NOW?
  • 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. Selenium PhantomJS as headless browser PHP -> node.js -> PHP ... which leads to a problem
  • 11. Selenium Two different, independent PHP processes Which fixture should the application load?
  • 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. 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. 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. 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. Selenium Neat side effects: • Developing without internet! • Change API responses for development
  • 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. 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. 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. WebDriver Would only need minor adjustments to also work in PHPUnit/Symfony WebTestCase
  • 22. GitlabCI CI is executing tests as well Tests might not be mocked Test will be mocked Conflicts while making a new build
  • 23. GitlabCI <?php // ... ! if ($container->hasParameter('is_ci')) { VCR::configure()->setMode(VCR::MODE_NONE); } ! // ...
  • 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. 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. Wrap up Would highly recommend it because it saves you a lot of time, work and nerves
  • 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