Laravel 4 Testing
Laravel 4 Testing
APPLICATIONS
Presented by Milan Popovi / @komita1981
ME
PHP developer
7 years in PHP development
Work for 12 Mnkys
I like to learn and share knowledge
Active member of PHP Srbija
YOU?
Who are you?
What's your experience in programming?
What's your experience in testing?
What are your expectations?
WHAT IS TESTING?
Testing is the activity of finding out whether a piece of code
produces the intended behavior
Prove you've done your work
Help you check much faster if you're work is done
Protect you from breaking things - regression bugs
Help you make better code design - easier to maintain
Let you apply changes with less worries - refactoring will
improve things without breaking anything
Ensures stable, long lasting application
Enhance security
Free documentation
IBM & Microsoft - TDD - 20-40% longer to complete but 4090% fewer bugs in production
TEST TYPES
Acceptance (end-to-end)
Test as if end user would use the whole system/feature
Integration
Test how different parts of system work together
Unit
Test single unit of code - mock all dependencies
What is to be tested?
EVERYTHING
PHPUNIT
Member of xUnit family
Created by Sebastian Bergmann
Integrated/Supported by all modern frameworks
Integrated in most IDE (PHPStorm, Netbeans, Eclipse, Zend
Studio)
class Calculator
{
public function add($a, $b)
{
return $a + $b;
}
}
/**
* @dataProvider getSuccessfulAddData
*/
public function testSuccessfulAdd($data)
{
$this->assertEquals($data['result'],
$this->calculator->add($data['a'], $data['b']));
}
public function getSuccessfulAddData()
{
return array(
array(
array('a' => 1, 'b' => 2, 'result' => 3),
array('a' => 2, 'b' => 1, 'result' => 3),
array('a' => 0, 'b' => 1, 'result' => 1),
array('a' => 1, 'b' => 0, 'result' => 1),
)
);
}
/**
* @dataProvider getUnsuccessfulAddData
*/
public function testUnsuccessfulAdd($data)
{
$this->setExpectedException($data['expectedException']);
$this->calculator->add($data['a'], $data['b']);
}
class Calculator
{
public function add($a, $b)
{
if (! is_int($a) or ! is_int($b)){
throw new Exception('Only integers allowed');
}
return $a + $b;
}
}
class ScientificCalculator
{
public function complex($a)
{
return "Too complex $a";
}
}
class Calculator
{
public function complex($a)
{
$scientificCalculator = new ScientificCalculator();
return $scientificCalculator->complex($a);
}
}
class ScientificCalculator
{
public function complex($a)
{
return "Too complex $a";
}
}
class Calculator
{
protected $scientificCalculator;
public function __construct(ScientificCalculator $scientificCalculator)
{
$this->scientificCalculator = $scientificCalculator;
}
public function complex($a)
{
return $this->scientificCalculator->complex($a);
}
}
MOCKERY
Simple, powerful framework for creating Mock Objects
Install through Composer
"require-dev": {
"mockery/mockery": "0.9.*@dev"
},
MOCK METHOD
$mockedObject = Mockery::mock('\Show\ExampleClass');
Partial mocks
$mockedObject = Mockery::mock('\Show\ExampleClass[save, send]');
$mockedObject = Mockery::mock('\Show\ExampleClass')->makePartial();
SHOULD RECEIVE
$this->mock->shouldReceive('methodName');
WITH
$this->mock
->shouldReceive('methodName')
->once()
->with($params);
AND RETURN
$mockedObject = Mockery::mock('\Show\ExampleClass');
$mockedObject
->shouldReceive('all')
->once()
->with($param)
->andReturn('foo');
TESTING IN LARAVEL 4
Built with unit testing in mind
Utilizes the Symfony HttpKernel, DomCrawler, and
BrowserKit components
All tests inherit app/tests/TestCase.php file
ApplicationTrait
cal(...) - Call the given URI and return the Response
action(...) - Call a controller action and return the Response
route(...) - Call a named route and return the Response
seed($class = 'DatabaseSeeder') - Seed a given database
connection
be(...) - Set the currently logged in user for the application
AssertionsTrait
assertResponseOk() - Assert that the client response has an
OK status code
assertResponseStatus($code) - Assert that the client
response has a given code
assertViewHas($key, $value = null) - Assert that the response
view has a given piece of bound data
assertRedirectedTo($uri, $with = array()) - Assert whether
the client was redirected to a given URI
MOCKING FACADES
public function crypt()
{
Crypt::setKey('someKey');
}
public function testCrypt()
{
Crypt::shouldReceive('setKey')->once()->with($key);
}
if(! $this->userModel->validate($userData)){
throw new StoreResourceFailedException($this->userModel->getErrors())
}
try{
$userModel = $this->userModel->create($userData);
if (! $userModel instanceof User){
throw new StoreResourceFailedException();
}
return $userModel;
}catch (Exception $e){
throw new StoreResourceFailedException('Failed');
use Mockery as m;
class UserControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->userModel = m::mock('Eloquent', 'Api\Models\User');
}
PROGRAMMING SINS
New Operators - new ClassName()
Using statics - SomeClass::someMethod()
Endless "anding" - Break SRP
PROGRAMMING SINS
Logic in constructor - only assign variables
Using switch-case often - use design patterns instead
Too many dependencies - max 4 dependencies
ADVICES
Try with writing tests after writing the code
Do not make tests complex
Do not duplicate test code
Treat test like your code
When you get confidence try to write tests before the code
ADVICES
Run tests often - after every change and before any commit
Test before refactoring
Use continuous integration server
http://images.sodahead.com/polls/001599249/4445136897_Q
https://lh4.ggpht.com/W3DVtNTVIAvZfJ99kDT2hP5cxklxZfLMG
http://www.redbubble.com/people/fitbys/works/10613559-re
http://www.slideshare.net/damiansromek/php-tests-tips
http://www.slideshare.net/ChonlasithJucksripor/unit-test-39
http://blog.typemock.com/2009/03/the-cost-of-test-driven-de
http://lh3.ggpht.com/-X8LPVvE5BYE/UHaLknLmMmI/AAAAAA
http://lh5.ggpht.com/-jDpF-eS-6TE/UQo_mozEkkI/AAAAAAAA
imgmax=800
THANK YOU
QUESTIONS?