Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Mocks, Stubs, Tests
Search
Alexandre Salomé
November 24, 2011
Programming
510
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Mocks, Stubs, Tests
Alexandre Salomé
November 24, 2011
More Decks by Alexandre Salomé
See All by Alexandre Salomé
Integrating WordPress and Symfony
alexandresalome
0
310
Symfony Form - Practical use cases
alexandresalome
2
220
Tests in a Symfony Application
alexandresalome
0
500
Les tests dans une application Symfony
alexandresalome
5
2.5k
Symfony Forms - Advanced Use Cases
alexandresalome
2
1k
Migrer vers une architecture micro-services : points de contrôle pour une migration réussie
alexandresalome
2
1.3k
Concevoir des back-offices performants
alexandresalome
1
780
Ma stratégie de tests
alexandresalome
0
340
Migrate from Symfony to Silex
alexandresalome
1
1.4k
Other Decks in Programming
See All in Programming
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
250
R8 の設定見直しでアプリサイズ削減
andpad
0
210
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.4k
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.1k
Kotlinの15年とServer-Side Kotlin
n_takehata
1
140
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.6k
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
470
Are APIs Still Relevant in the AI Era?
soyuka
0
460
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
730
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
160
CodeRabbitの効果検証と過ごしてみた3ヶ月
armondando
0
230
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
356
22k
The Invisible Side of Design
smashingmag
301
52k
First, design no harm
axbom
PRO
2
1.3k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
410
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
430
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Navigating Team Friction
lara
192
16k
The Limits of Empathy - UXLibs8
cassininazir
2
720
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
280
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Transcript
None
None
None
L’instant quizz
Qui a déjà écrit des tests ?
Qui a déjà utilisé PHPUnit ?
Qui a déjà mocké une classe ?
Séance de gym terminée. Merci
None
• – – – • – – •
•
• •
• •
• • – • – • – • Le format
des tests dépend du sujet
Quand je casserais quelque chose Elle ne me ralentira pas
dans mon travail Le code coverage sera de 100%
Quand je casserais quelque chose Elle ne me ralentira pas
dans mon travail Le code coverage sera de 100%
None
22,4% 97% 42% Pas bien Bien
22,4% 97% 42% Pas bien Bien
•
• • •
• • • –
• • • – –
class PHPTour { public $totalCost; public $attendees; public function getPlacePrice()
{ return $this->totalCost / $this->attendees; } }
class PHPTourTest extends PHPUnit_Framework_TestCase { public function testForCoverage() { $tour
= new PHPTour(); $tour->totalCost = 40000; $tour->attendees = 100; $this->assertEquals(400, $tour->getPlacePrice()); } }
class PHPTourTest extends PHPUnit_Framework_TestCase { public function testForCoverage() { $tour
= new PHPTour(); $tour->totalCost = 40000; $tour->attendees = 100; $this->assertEquals(400, $tour->getPlacePrice()); } }
$tour->attendees = 0;
$tour->attendees = 0; Division par zéro
None
• – •
<?php class CodeCoverage { private $field1; // … private $fieldN;
// … private $field30; // Powerpoint coding standards public function setFieldN($n) { $this->fieldn = $n; } public function getFieldN() { return $this->fieldN; } }
<?php class CodeCoverage { // … public function compute() {
$troll = $field1 * $field2 / (($field3 * $field4) * $field5) * $field6 / $field7 * $field8; $troll2 = $field9 * $field10 / cos($field11); $troll3 = $field12 * tan($field13); return $troll * log($troll2) / sin($troll3) * $field14 /* (;;)(^_^)(;;) */; } }
<?php class CodeCoverageTest extends PHPUnit_Framework_TestCase { public function testSetField1AndGetField1ReturnsCorrectValue() {
$cc = new CodeCoverage(); $cc->setField1(’fuu'); $this->assertEquals(’fuu', $cc->getField1()); } // repeat for each fields }
None
• • • • • •
•
• • – –
• • – – –
None
<?php // Insert your code here
<?php class Car { public function __construct() { $this->engine =
new Engine(); } }
<?php class Car { public function __construct() { $this->engine =
new Engine(); } }
<?php class Car { public function __construct(EngineInterface $engine) { $this->engine
= $engine; } }
<?php class Car { public function __construct(EngineInterface $engine) { $this->engine
= $engine; } }
<?php class SausageShop { public function serve() { $sausage =
SausageFactory::getNewSausage(); $bread = BreadFactory::getNewBread(); return $bread->upgradeWith($sausage); } }
<?php class SausageShop { public function serve() { $sausage =
SausageFactory::getNewSausage(); $bread = BreadFactory::getNewBread(); return $bread->upgradeWith($sausage); } }
<?php class SausageShop { public function __construct( SausageFactory $sausageFactory, BreadFactory
$breadFactory ) { $this->sausageFactory = $sausageFactory; $this->breadFactory = $breadFactory; } public function serve() { $sausage = $this->sausageFactory->getNewSausage(); $bread = $this->breadFactory->getNewBread(); return $bread->upgradeWith($sausage); } }
<?php class SausageShop { public function __construct( SausageFactory $sausageFactory, BreadFactory
$breadFactory ) { $this->sausageFactory = $sausageFactory; $this->breadFactory = $breadFactory; } public function serve() { $sausage = $this->sausageFactory->getNewSausage(); $bread = $this->breadFactory->getNewBread(); return $bread->upgradeWith($sausage); } }
<?php class Customer { public function orderBeer() { $url =
'http://waiter/bring-me-a- beer/erdinger'; return file_get_contents($url); } }
<?php class Customer { public function orderBeer() { $url =
'http://waiter/bring-me-a- beer/erdinger'; return file_get_contents($url); } }
<?php class Customer { public function orderBeer( WaiterApi $api) {
return $api->bring(‘erdinger’); } }
<?php class Customer { public function orderBeer( WaiterApi $api) {
return $api->bring(‘erdinger’); } }
Design by contract
SINGLETONS
None
None
None
None
<?php abstract class BaseMedia { const TYPE_IMAGE; abstract public function
getFile(); public function getType() { switch (get_extension($this->getFile())) { case 'png‘: return self::TYPE_IMAGE; } }
<?php abstract class BaseMedia { const TYPE_IMAGE; abstract public function
getFile(); public function getType() { switch (get_extension($this->getFile())) { case 'png‘: return self::TYPE_IMAGE; } }
<?php Interface MediaInterface { const TYPE_IMAGE; public function getType(); }
None
• •
• • – –
• • Les mocks/stubs à notre secours !
None
• • • •
• – – • •
• • • – – • • • •
JIHANE MOSSALIM
•
<?php class MyClassTest extends PHPUnit_Framework_TestCase { public function testFoo() {
$engine = $this->getMock('Engine'); $car = new Car($engine); } } Tous les appels à Engine renverront « null » En fait… c‘est un stub
• • – – •
<?php // ... $engine = $this->getMock('Engine'); $engine ->expects($this->once()) ->method(‘start‘) ->will($this->returnValue(true))
; Un contrat est établi C’est un mock, un vrai
• $mock • ->expects(…) • ->method('name') • ->with(…) • ->will(…)
expects(PHPUnit_…_Matcher_Invocation) $this->exactly($n) $this->never() $this->any() $this->atLeastOnce()
with(PHPUnit_Framework_Constraint) $this->exactly($n) $this->arrayHasKey ('...') $this->any()
will(PHPUnit_Framework_MockObject_Stub) $this->returnValue($value) $this->returnArgument($n) $this->returnCallback($c) $this->throwException($e) $this->onConsecutiveCalls(1, 2, 3)
None
<?php namespace Sensio\Bundle\PlatformBundle\OAuth; use Symfony\Component\HttpFoundation\Session; class OAuthClient { // …
properties declaration … public function __construct($serviceName, \OAuth $oauth, $endPoint, $authorizeUri, $requestTokenUri, $accessTokenUri, Session $session = null) { $this->serviceName = $serviceName; $this->oauth = $oauth; $this->endPoint = $endPoint; $this->authorizeUri = $authorizeUri; $this->requestTokenUri = $requestTokenUri; $this->accessTokenUri = $accessTokenUri; $this->session = $session; $this->sessionOAuthTokenName = sprintf('oauth/_%s.oauth_token', $this->serviceName); $this->sessionOAuthTokenSecretName = sprintf('oauth/_%s.oauth_token_secret', $this->serviceName); } // … other methods …
public function getRequestToken($redirectUri = null) { if ($this->session) { $this->session->remove($this->sessionOAuthTokenName);
$this->session->remove($this->sessionOAuthTokenSecretName); } $requestToken = $this->oauth->getRequestToken( $this->requestTokenUri, $redirectUri); if ($requestToken === false) { throw new \OAuthException('Failed fetching request token, response was: ’ .$this->oauth->getLastResponse()); } if ($this->session) { $this->session->set($this->sessionOAuthTokenName, $requestToken['oauth_token']); $this->session->set($this->sessionOAuthTokenSecretName, $requestToken['oauth_token_secret']); } return $requestToken; }
public function retrieveAccessToken($oauthSessionHandle = '', $verifierToken) { if ($this->session) {
if (($token = $this->session->get($this->sessionOAuthTokenName)) && ($tokenSecret = $this->session->get( $this->sessionOAuthTokenSecretName)) ) { $this->oauth->setToken($token, $tokenSecret); } } $response = $this->oauth->getAccessToken($this->accessTokenUri, $oauthSessionHandle, $verifierToken); if (false === $response) { throw new \OAuthException('Failed fetching access token, response was: '. $this->oauth->getLastResponse()); } return $response; } }
public function setToken($token, $tokenSecret) { $this->oauth->setToken($token, $tokenSecret); } public function
get($path) { $url = sprintf('%s/%s', $this->endPoint, ltrim($path, '/')); $state = $this->oauth->fetch($url); if (!$state) { throw new \RuntimeException(sprintf(Can\’t fetch resource %s', $url)); } return $this->oauth->getLastResponse(); }
•
class myTest extends PHPUnit_Framework_TestCase { public function testGetRequestToken() { $oauth
= $this->getMock('OAuth'); $oauth ->expects($this->once()) ->method('getRequestToken') ->will($this->returnValue('ok')) ; $client = new OAuthClient( 'foo', $oauth, 'bar', 'bar', 'bar', 'bar', 'bar'); $this->assertEquals('ok', $client->getRequestToken()); } }
class myTest extends PHPUnit_Framework_TestCase { /** @expectedException LogicException */ public
function testGetRequestTokenWithError() { $oauth = $this->getMock('OAuth'); $oauth ->expects($this->once()) ->method('getRequestToken') ->will($this->returnValue(false)); $client = new OAuthClient('foo', $oauth, 'bar', 'bar', 'bar', 'bar', 'bar'); $client->getRequestToken(); } }
• – – • – – • –
Questions?
None