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
300
Symfony Form - Practical use cases
alexandresalome
2
210
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
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
360
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
570
速習iPhone Duo対応
yuukiw00w
2
760
Security issues being discussed on Web Platforms
petamoriken
0
1.2k
一人だけ、Kiroが静止する日
hideg
0
130
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
250
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
6
13k
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
210
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
360
AWSに止められる覚悟してますか?
morizo_1984
1
300
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
160
Featured
See All Featured
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
500
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Designing for humans not robots
tammielis
254
26k
A Modern Web Designer's Workflow
chriscoyier
699
190k
How to make the Groovebox
asonas
2
2.5k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
76k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
It's Worth the Effort
3n
188
29k
Facilitating Awesome Meetings
lara
57
7.1k
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