SlideShare ist ein Scribd-Unternehmen logo
1 von 26
Development Workshops PHP Unit Testing @ Tagged   “ We enable anyone to meet and socialize with new people” 2011.10.26 Erik Johannessen
PHP Unit Testing @ Tagged Goal: - Gain familiarity with unit tests and unit testing here at Tagged - Gain familiarity with the testing framework currently in place - Learn to write (better) unit tests
Agenda ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
What is a Unit Test? - A unit is the smallest testable part of an application.   - Exercises a particular piece of code in isolation, ensuring correctness.   - Good for regression testing.  Once we have a test that passes, the test should continue to pass on each successive change to the codebase.
Unit Test Attributes - Each test should be independent of all other tests (including itself!)   - The number of times/order in which they're run shouldn't matter.   - This is achieved by beginning with a controlled state, and feeding in controlled inputs.   - Controlled inputs should produce expected outputs.   - State should change in predictable ways, given inputs.   - External dependencies (DB, Cache, other external services) should be mocked out.
Unit Tests in PHP - All tests are found in the directory /cooltest/unit/tests/   - Each test file should end in *Test.php   - Each test should be a public methods with name prefixed with “test”.   - Tests are run in an unspecified order; do not depend on one test running before another.   - Before each test is run, the setUp() method is invoked, if it exists.   - After each test is run, the tearDown() method is invoked, if it exists.
myclassTest.php Tests shared/class/tag/myclass.php class tag_myclassTest extends test_base {     public function setUp() {         parent::setUp();         // do setup stuff before every test     }          public function testMethodA() {         // call method a() on an instance of myclass         // assert some conditions     }          public function testMethodB() {         // call method b() on an instance of myclass         // assert some conditions     }     public function tearDown() {         parent::tearDown();         // perform cleanup         // in most cases, don't need this, as test_base::tearDown() will         // take care of almost everything for you     } }
Running the tests using PHPUnit > pwd /home/html/cooltest/unit/tests/shared/class/tag # run all tests in this directory > phpunit . # run all tests in myclassTest.php > phpunit myclassTest.php # run testMethodA > phpunit –-filter testMethodA myclassTest.php # run all tests that begin with testMethod* > phpunit –-filter testMethod myclassTest.php
Assertions Testing framework comes with several built-in assertion functions. If the optional $msgOnFailure is given, it will be included in the output when the test fails.  I highly recommend including descriptive failure messages, as that not only helps the debugger find out what failed, but also what the intention of the test author was. public function test() {     $this->assertTrue($value, $msgOnFailure = '');     $this->assertFalse($value, $msgOnFailure = '');     $this->assertEquals($expected, $actual, $msgOnFailure = '');     $this->assertNotEquals($expected, $actual, $msgOnFailure = '');     $this->assertType($expected, $actual, $msgOnFailure = '');     $this->assertGreaterThan($expected, $actual, $msgOnFailure = ''); }
Mocking Objects in PHP - Almost all classes in our codebase have dependencies on other classes.   - To eliminate those dependencies as a variable in a unit test, we replace those objects that we would normally fetch from the global loader ($_TAG) with mock objects.   - Mock objects are just like the real objects they substitute for, except that we override the values of methods, properties and constants of that object to produce dependable, controlled results when the object is invoked.
Mocking Objects in PHP // in the API file public function getGoldBalance($params) {     $userId = $this->_requestUserId(true);     // here, $_TAG->gold[$userId] returns our mock object     $userGold = $_TAG->gold[$userId]->getGoldBalance(true);     $results = array(         'gold_bal' => $userGold,         'gold_bal_string' => number_format($userGold, 0)     );     return $this->generateResult($results); } // in the test file $userId = 9000; $balance = 500; $goldGlobalMock = GlobalMockFactory::getGlobalMock('tag_user_gold', 'gold', $userId); $goldGlobalMock->override_method('getGoldBalance', function($getFromDB=false) use ($balance) {     return $balance; }); $goldGlobalMock->mock(); $result = tag_api::call('tagged.gold.getBalance', array(), $userId); $this->assertEquals($balance, $result['gold_bal'], 'Wrong balance returned!');
Mocking Objects in PHP $globalMock->override_property('myProp', 1000); $mockObj = $globalMock->mock(); // prints 1000 echo $mockObj->myProp; $globalMock->override_constant('MY_CONST', 5); $mockObj = $globalMock->mock(); // prints 5 echo $mockObj::MY_CONST;   Can also be used to add methods/properties to objects that don't already have them.
Mocking Static Functions in PHP $commMock = new StaticMock('tag_privacy', 'can_communicate', true); $userId = 9000; $otherUserId = 9001; // always returns true! $canCommunicate = tag_privacy::can_communicate($userId, $otherUserId); $this->assertTrue($canCommunicate, “Users can't communicate!”); // a more dynamic example $goodUserId = 9002 $badUserId = 9003; $boxedMock = new StaticMock('tag_user_auth', 'is_boxed_user', function ($userId) use ($badUserId) {     return $userId == $badUserId; }); $this->assertTrue(tag_user_auth::is_boxed_user($badUserId), 'Bad user not boxed!'); $this->assertFalse(tag_user_auth::is_boxed_user($goodUserId), 'Good user boxed!');
Testing for Errors - Not found often in our codebase, but we can test for and trap specific errors within the PHP.   - Specify file and error level, then verify number of errors trapped by testErrorHandler. $errorHandler = new testErrorHandler(); $errorHandler->suppressError('shared/class/tag/user/invites.php', E_USER_NOTICE); $result = $invites->removeOutgoingInvite($connId); $this->assertEquals(1, $errorHandler->numErrorsSuppressed(), 'Notice not triggered.'); $errorHandler->restorePreviousHandler();
Getting Real Objects in PHP - Most times, we don't want a mock object for the object under test –- we want the real thing. - However, if we just go and get an object via our global system (i.e.  $_TAG->contacts[$userId]), our test will be dependent on whatever object might be found in memcache. - test_base::get_global_object() solves this by figuring out how to create an object directly, and returning a new one, with a mock loader to avoid touching memcache. // assume this is a test class that inherits from test_base $userId = 9000; // returns a fresh instance of tag_user_contacts // but with a mock loader // normally accessed like $_TAG->contacts[$userId]; $userContacts = self::get_global_object('contacts', $userId);
Framework Limitations Can't pass use variables by reference to overridden methods. Can't mock static functions that contain static variables. public static function is_school_supported($userId) {     static $country_supported = array('US', 'CA', 'GB', 'IE', 'NZ', 'AU');     $userObj = $_TAG->user[$userId];     if (empty($userObj) || !$userObj->isValidUser()) return false;     $countryCode = 'US';     $address = $userObj->getAddressObj();     if ($address){         $countryCode = $address->getCountryCode();     }     if (in_array($countryCode, $country_supported))         return true;     else         return false; } $balance = 5000; $mock->override_method('credit', function($amt) use (&$balance) {      $balance += $amt;      return $balance; });
Hudson - Our unit testing suite (currently >900 tests) is also very useful for regression testing.   - Our continuous integration system, Hudson, runs every test after every SVN submission to web.   - If any test fails, our codebase has regressed, and the commit author that broke the build is notified (as is proddev@tagged.com, so it's nice and public).   - If you break the build, please respond promptly to fix it; we can't ship with a broken build.
http://webbuild.tag-dev.com/hudson/job/Web/
 
Let's do an example - Wink! class tag_apps_winkTest extends test_base {     public function setUp() {         parent::setUp();         $this->_userId = 9000;                  $winkDaoGlobalMock = GlobalMockFactory::getGlobalMock('tag_dao_wink', 'dao', array('wink', $this->_userId));         $winkDaoGlobalMock->override_method('getWinks', function() {             return array(                 0 => array(                     'other_user_id' => 9001,                     'time' => $_SERVER['REQUEST_TIME'],                     'type'  => 'R',                     'is_viewed' => 'N'                 ),             );         });         $winkDaoGlobalMock->mock();         $this->_mockUser(9001);         $this->_wink = self::get_global_object('wink', $this->_userId);     }          public function testCountWink() {         $numWinks = $this->_wink->countWinks();         $this->assertEquals(1, $numWinks, "wrong number of winks!");     } }
Other Testing Strategies – Corner Cases Call functions under test with corner case inputs     - 0     - null     - ''           (an empty string)     - array()      (an empty array)     - Big numbers  (both positive & negative)     - Long strings     - Other large inputs (esp. where constants like MAX_SIZE are defined)
Other Testing Strategies – Negative Testing Bad/illegal inputs should throw exceptions, raise errors, or otherwise alert the programmer of bad input // test that an exception is thrown try {     $result = tag_api::call('tagged.apps.gifts.getGiftRecipients', array('goldTxnId' => 0), $this->_userId);     $this->fail('getGiftRecipients did not throw an exception for invalid id'); } catch (Exception $e) {     $this->assertEquals(107, $e->code(), 'Wrong exception code'); } // test that an error is triggered $errorHandler = new testErrorHandler(); $errorHandler->suppressError('shared/class/tag/user/invites.php', E_USER_NOTICE); $result = $invites->removeOutgoingInvite($connectionId); $this->assertEquals(1,$errorHandler->numErrorsSuppressed(),'Notice not triggered'); $errorHandler->restorePreviousHandler();
Other Testing Strategies – Differing Initial States Set up tests to begin with differing initial states // test that you can get a friend id from a user's friend list public function testGetRandomFriend() {     $friendList = array(34, 55, 88);     $friends = new Friends($friendList);     $randomFriend = $friends->getRandomFriend();     $this->assertTrue(in_array($randomFriend, $friendList), 'Got non-friend!'); } // test that you can't get a friend id when a user has no friends public function testGetRandomFriendWithNoFriends() {     $friendList = array();     $friends = new Friends($friendList);     $randomFriend = $friends->getRandomFriend();     $this->assertTrue(is_null($randomFriend), 'Got a friend from user with no friends!'); }
Other Testing Strategies  Tests should be as granular as possible -- each test should be its own function. // BAD $this->assertEquals(10, $objUnderTest->resultsPerPage()); // BETTER $this->assertEquals($objUnderTest::RESULTS_PER_PAGE, $objUnderTest->resultsPerPage()); Test assertions should be implementation-agnostic.  Changing the internal implementation of a method should not break the test. public function testAddAndRemoveFriend() {      $friendId = 54;       $friends = new Friends();      $friends->add($friendId);       $this->assertTrue($friends->isFriend($friendId));      // you should stop here, below this should be a separate test       $friends->remove($friendId);      $this->assertFalse($friends->isFriend($friendId)); }
Test-Driven Development Stub out the methods for your class first, then write unit tests for that class. - At first, all tests will fail. - Write your class methods. - When all tests pass, you're done!   Also good for bug fixes. If you find a bug caused by unintended code behaviour,  write a test that asserts the correct behaviour.  When the test passes, the bug is fixed!
Writing Testable Code Testing a unit code involves sealing off the “seams” with mock objects and canned results. Introduce seams in your code to help with testing: - Modularize methods - Use setters/getters - Pass objects to a class' constructor   The following common coding practices make testing very difficult: - Creating monolithic functions that handle more than one responsibility - Using global variables - Creating objects within methods instead of asking for them tag_email::send(new tag_email_options($userId, 'cafe_convertgold', $data));

Weitere ähnliche Inhalte

Was ist angesagt?

Scaladays 2014 introduction to scalatest selenium dsl
Scaladays 2014   introduction to scalatest selenium dslScaladays 2014   introduction to scalatest selenium dsl
Scaladays 2014 introduction to scalatest selenium dslMatthew Farwell
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and EasybIakiv Kramarenko
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF SummitOrtus Solutions, Corp
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQueryKnoldus Inc.
 
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...Iakiv Kramarenko
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma Christopher Bartling
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and JasmineAngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasminefoxp2code
 
Intro to testing Javascript with jasmine
Intro to testing Javascript with jasmineIntro to testing Javascript with jasmine
Intro to testing Javascript with jasmineTimothy Oxley
 
Unit testing JavaScript: Jasmine & karma intro
Unit testing JavaScript: Jasmine & karma introUnit testing JavaScript: Jasmine & karma intro
Unit testing JavaScript: Jasmine & karma introMaurice De Beijer [MVP]
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit TestChiew Carol
 
Apache Ant
Apache AntApache Ant
Apache AntAli Bahu
 
Unit and functional testing with Siesta
Unit and functional testing with SiestaUnit and functional testing with Siesta
Unit and functional testing with SiestaGrgur Grisogono
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSJim Lynch
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Ant - Another Neat Tool
Ant - Another Neat ToolAnt - Another Neat Tool
Ant - Another Neat ToolKanika2885
 
Unit testing of java script and angularjs application using Karma Jasmine Fra...
Unit testing of java script and angularjs application using Karma Jasmine Fra...Unit testing of java script and angularjs application using Karma Jasmine Fra...
Unit testing of java script and angularjs application using Karma Jasmine Fra...Samyak Bhalerao
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introductionNir Kaufman
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineGil Fink
 

Was ist angesagt? (20)

Scaladays 2014 introduction to scalatest selenium dsl
Scaladays 2014   introduction to scalatest selenium dslScaladays 2014   introduction to scalatest selenium dsl
Scaladays 2014 introduction to scalatest selenium dsl
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
 
Automation patterns on practice
Automation patterns on practiceAutomation patterns on practice
Automation patterns on practice
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
 
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and JasmineAngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasmine
 
Intro to testing Javascript with jasmine
Intro to testing Javascript with jasmineIntro to testing Javascript with jasmine
Intro to testing Javascript with jasmine
 
Unit testing JavaScript: Jasmine & karma intro
Unit testing JavaScript: Jasmine & karma introUnit testing JavaScript: Jasmine & karma intro
Unit testing JavaScript: Jasmine & karma intro
 
Angular testing
Angular testingAngular testing
Angular testing
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit Test
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
Unit and functional testing with Siesta
Unit and functional testing with SiestaUnit and functional testing with Siesta
Unit and functional testing with Siesta
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Ant - Another Neat Tool
Ant - Another Neat ToolAnt - Another Neat Tool
Ant - Another Neat Tool
 
Unit testing of java script and angularjs application using Karma Jasmine Fra...
Unit testing of java script and angularjs application using Karma Jasmine Fra...Unit testing of java script and angularjs application using Karma Jasmine Fra...
Unit testing of java script and angularjs application using Karma Jasmine Fra...
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmine
 

Ähnlich wie PHP Unit Testing

Using of TDD practices for Magento
Using of TDD practices for MagentoUsing of TDD practices for Magento
Using of TDD practices for MagentoIvan Chepurnyi
 
Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit TestingMike Lively
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitmfrost503
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitmfrost503
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Best Practice Testing with Lime 2
Best Practice Testing with Lime 2Best Practice Testing with Lime 2
Best Practice Testing with Lime 2Bernhard Schussek
 
From typing the test to testing the type
From typing the test to testing the typeFrom typing the test to testing the type
From typing the test to testing the typeWim Godden
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEnterprise PHP Center
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPWildan Maulana
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl TechniquesDave Cross
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Michelangelo van Dam
 
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QACreating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QAarchwisp
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Jason Lotito
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 

Ähnlich wie PHP Unit Testing (20)

Using of TDD practices for Magento
Using of TDD practices for MagentoUsing of TDD practices for Magento
Using of TDD practices for Magento
 
Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit Testing
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Best Practice Testing with Lime 2
Best Practice Testing with Lime 2Best Practice Testing with Lime 2
Best Practice Testing with Lime 2
 
From typing the test to testing the type
From typing the test to testing the typeFrom typing the test to testing the type
From typing the test to testing the type
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QACreating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 

Kürzlich hochgeladen

Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666nishakur201
 
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝soniya singh
 
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual serviceanilsa9823
 
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual serviceanilsa9823
 
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,dollysharma2066
 
The Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by MindbrushThe Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by MindbrushShivain97
 
Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...
Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...
Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...anilsa9823
 
Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...
Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...
Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...CIOWomenMagazine
 
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改atducpo
 
LC_YouSaidYes_NewBelieverBookletDone.pdf
LC_YouSaidYes_NewBelieverBookletDone.pdfLC_YouSaidYes_NewBelieverBookletDone.pdf
LC_YouSaidYes_NewBelieverBookletDone.pdfpastor83
 
call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..nishakur201
 
Lilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptxLilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptxABMWeaklings
 
CALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual serviceanilsa9823
 
Top Rated Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...Call Girls in Nagpur High Profile
 
Breath, Brain & Beyond_A Holistic Approach to Peak Performance.pdf
Breath, Brain & Beyond_A Holistic Approach to Peak Performance.pdfBreath, Brain & Beyond_A Holistic Approach to Peak Performance.pdf
Breath, Brain & Beyond_A Holistic Approach to Peak Performance.pdfJess Walker
 
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdfREFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdfssusere8ea60
 
$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...
$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...
$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...PsychicRuben LoveSpells
 
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girlsPooja Nehwal
 
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...ur8mqw8e
 

Kürzlich hochgeladen (20)

Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666Call Girls Anjuna beach Mariott Resort ₰8588052666
Call Girls Anjuna beach Mariott Resort ₰8588052666
 
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
Call Girls in Kalyan Vihar Delhi 💯 Call Us 🔝8264348440🔝
 
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Rajajipuram Lucknow best sexual service
 
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Aliganj Lucknow best sexual service
 
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
8377087607 Full Enjoy @24/7-CLEAN-Call Girls In Chhatarpur,
 
escort service sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974
escort service  sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974escort service  sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974
escort service sasti (*~Call Girls in Paschim Vihar Metro❤️9953056974
 
The Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by MindbrushThe Selfspace Journal Preview by Mindbrush
The Selfspace Journal Preview by Mindbrush
 
Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...
Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...
Lucknow 💋 High Class Call Girls Lucknow 10k @ I'm VIP Independent Escorts Gir...
 
Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...
Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...
Understanding Relationship Anarchy: A Guide to Liberating Love | CIO Women Ma...
 
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
文凭办理《原版美国USU学位证书》犹他州立大学毕业证制作成绩单修改
 
LC_YouSaidYes_NewBelieverBookletDone.pdf
LC_YouSaidYes_NewBelieverBookletDone.pdfLC_YouSaidYes_NewBelieverBookletDone.pdf
LC_YouSaidYes_NewBelieverBookletDone.pdf
 
call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..call girls in candolim beach 9870370636] NORTH GOA ..
call girls in candolim beach 9870370636] NORTH GOA ..
 
Lilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptxLilac Illustrated Social Psychology Presentation.pptx
Lilac Illustrated Social Psychology Presentation.pptx
 
CALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Mahanagar Lucknow best sexual service
 
Top Rated Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Tingre Nagar ⟟ 6297143586 ⟟ Call Me For Genuine Se...
 
Breath, Brain & Beyond_A Holistic Approach to Peak Performance.pdf
Breath, Brain & Beyond_A Holistic Approach to Peak Performance.pdfBreath, Brain & Beyond_A Holistic Approach to Peak Performance.pdf
Breath, Brain & Beyond_A Holistic Approach to Peak Performance.pdf
 
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdfREFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
REFLECTIONS Newsletter Jan-Jul 2024.pdf.pdf
 
$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...
$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...
$ Love Spells^ 💎 (310) 882-6330 in West Virginia, WV | Psychic Reading Best B...
 
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
9892124323, Call Girls in mumbai, Vashi Call Girls , Kurla Call girls
 
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
《塔夫斯大学毕业证成绩单购买》做Tufts文凭毕业证成绩单/伪造美国假文凭假毕业证书图片Q微信741003700《塔夫斯大学毕业证购买》《Tufts毕业文...
 

PHP Unit Testing

  • 1. Development Workshops PHP Unit Testing @ Tagged   “ We enable anyone to meet and socialize with new people” 2011.10.26 Erik Johannessen
  • 2. PHP Unit Testing @ Tagged Goal: - Gain familiarity with unit tests and unit testing here at Tagged - Gain familiarity with the testing framework currently in place - Learn to write (better) unit tests
  • 3.
  • 4. What is a Unit Test? - A unit is the smallest testable part of an application.   - Exercises a particular piece of code in isolation, ensuring correctness.   - Good for regression testing.  Once we have a test that passes, the test should continue to pass on each successive change to the codebase.
  • 5. Unit Test Attributes - Each test should be independent of all other tests (including itself!)   - The number of times/order in which they're run shouldn't matter.   - This is achieved by beginning with a controlled state, and feeding in controlled inputs.   - Controlled inputs should produce expected outputs.   - State should change in predictable ways, given inputs.   - External dependencies (DB, Cache, other external services) should be mocked out.
  • 6. Unit Tests in PHP - All tests are found in the directory /cooltest/unit/tests/   - Each test file should end in *Test.php   - Each test should be a public methods with name prefixed with “test”.   - Tests are run in an unspecified order; do not depend on one test running before another.   - Before each test is run, the setUp() method is invoked, if it exists.   - After each test is run, the tearDown() method is invoked, if it exists.
  • 7. myclassTest.php Tests shared/class/tag/myclass.php class tag_myclassTest extends test_base {     public function setUp() {         parent::setUp();         // do setup stuff before every test     }         public function testMethodA() {         // call method a() on an instance of myclass         // assert some conditions     }         public function testMethodB() {         // call method b() on an instance of myclass         // assert some conditions     }     public function tearDown() {         parent::tearDown();         // perform cleanup         // in most cases, don't need this, as test_base::tearDown() will         // take care of almost everything for you     } }
  • 8. Running the tests using PHPUnit > pwd /home/html/cooltest/unit/tests/shared/class/tag # run all tests in this directory > phpunit . # run all tests in myclassTest.php > phpunit myclassTest.php # run testMethodA > phpunit –-filter testMethodA myclassTest.php # run all tests that begin with testMethod* > phpunit –-filter testMethod myclassTest.php
  • 9. Assertions Testing framework comes with several built-in assertion functions. If the optional $msgOnFailure is given, it will be included in the output when the test fails.  I highly recommend including descriptive failure messages, as that not only helps the debugger find out what failed, but also what the intention of the test author was. public function test() {     $this->assertTrue($value, $msgOnFailure = '');     $this->assertFalse($value, $msgOnFailure = '');     $this->assertEquals($expected, $actual, $msgOnFailure = '');     $this->assertNotEquals($expected, $actual, $msgOnFailure = '');     $this->assertType($expected, $actual, $msgOnFailure = '');     $this->assertGreaterThan($expected, $actual, $msgOnFailure = ''); }
  • 10. Mocking Objects in PHP - Almost all classes in our codebase have dependencies on other classes.   - To eliminate those dependencies as a variable in a unit test, we replace those objects that we would normally fetch from the global loader ($_TAG) with mock objects.   - Mock objects are just like the real objects they substitute for, except that we override the values of methods, properties and constants of that object to produce dependable, controlled results when the object is invoked.
  • 11. Mocking Objects in PHP // in the API file public function getGoldBalance($params) {     $userId = $this->_requestUserId(true);     // here, $_TAG->gold[$userId] returns our mock object     $userGold = $_TAG->gold[$userId]->getGoldBalance(true);     $results = array(         'gold_bal' => $userGold,         'gold_bal_string' => number_format($userGold, 0)     );     return $this->generateResult($results); } // in the test file $userId = 9000; $balance = 500; $goldGlobalMock = GlobalMockFactory::getGlobalMock('tag_user_gold', 'gold', $userId); $goldGlobalMock->override_method('getGoldBalance', function($getFromDB=false) use ($balance) {     return $balance; }); $goldGlobalMock->mock(); $result = tag_api::call('tagged.gold.getBalance', array(), $userId); $this->assertEquals($balance, $result['gold_bal'], 'Wrong balance returned!');
  • 12. Mocking Objects in PHP $globalMock->override_property('myProp', 1000); $mockObj = $globalMock->mock(); // prints 1000 echo $mockObj->myProp; $globalMock->override_constant('MY_CONST', 5); $mockObj = $globalMock->mock(); // prints 5 echo $mockObj::MY_CONST;   Can also be used to add methods/properties to objects that don't already have them.
  • 13. Mocking Static Functions in PHP $commMock = new StaticMock('tag_privacy', 'can_communicate', true); $userId = 9000; $otherUserId = 9001; // always returns true! $canCommunicate = tag_privacy::can_communicate($userId, $otherUserId); $this->assertTrue($canCommunicate, “Users can't communicate!”); // a more dynamic example $goodUserId = 9002 $badUserId = 9003; $boxedMock = new StaticMock('tag_user_auth', 'is_boxed_user', function ($userId) use ($badUserId) {     return $userId == $badUserId; }); $this->assertTrue(tag_user_auth::is_boxed_user($badUserId), 'Bad user not boxed!'); $this->assertFalse(tag_user_auth::is_boxed_user($goodUserId), 'Good user boxed!');
  • 14. Testing for Errors - Not found often in our codebase, but we can test for and trap specific errors within the PHP.   - Specify file and error level, then verify number of errors trapped by testErrorHandler. $errorHandler = new testErrorHandler(); $errorHandler->suppressError('shared/class/tag/user/invites.php', E_USER_NOTICE); $result = $invites->removeOutgoingInvite($connId); $this->assertEquals(1, $errorHandler->numErrorsSuppressed(), 'Notice not triggered.'); $errorHandler->restorePreviousHandler();
  • 15. Getting Real Objects in PHP - Most times, we don't want a mock object for the object under test –- we want the real thing. - However, if we just go and get an object via our global system (i.e.  $_TAG->contacts[$userId]), our test will be dependent on whatever object might be found in memcache. - test_base::get_global_object() solves this by figuring out how to create an object directly, and returning a new one, with a mock loader to avoid touching memcache. // assume this is a test class that inherits from test_base $userId = 9000; // returns a fresh instance of tag_user_contacts // but with a mock loader // normally accessed like $_TAG->contacts[$userId]; $userContacts = self::get_global_object('contacts', $userId);
  • 16. Framework Limitations Can't pass use variables by reference to overridden methods. Can't mock static functions that contain static variables. public static function is_school_supported($userId) {     static $country_supported = array('US', 'CA', 'GB', 'IE', 'NZ', 'AU');     $userObj = $_TAG->user[$userId];     if (empty($userObj) || !$userObj->isValidUser()) return false;     $countryCode = 'US';     $address = $userObj->getAddressObj();     if ($address){         $countryCode = $address->getCountryCode();     }     if (in_array($countryCode, $country_supported))         return true;     else         return false; } $balance = 5000; $mock->override_method('credit', function($amt) use (&$balance) {     $balance += $amt;      return $balance; });
  • 17. Hudson - Our unit testing suite (currently >900 tests) is also very useful for regression testing.   - Our continuous integration system, Hudson, runs every test after every SVN submission to web.   - If any test fails, our codebase has regressed, and the commit author that broke the build is notified (as is proddev@tagged.com, so it's nice and public).   - If you break the build, please respond promptly to fix it; we can't ship with a broken build.
  • 19.  
  • 20. Let's do an example - Wink! class tag_apps_winkTest extends test_base {     public function setUp() {         parent::setUp();         $this->_userId = 9000;                 $winkDaoGlobalMock = GlobalMockFactory::getGlobalMock('tag_dao_wink', 'dao', array('wink', $this->_userId));         $winkDaoGlobalMock->override_method('getWinks', function() {             return array(                 0 => array(                     'other_user_id' => 9001,                     'time' => $_SERVER['REQUEST_TIME'],                     'type'  => 'R',                     'is_viewed' => 'N'                 ),             );         });         $winkDaoGlobalMock->mock();         $this->_mockUser(9001);         $this->_wink = self::get_global_object('wink', $this->_userId);     }         public function testCountWink() {         $numWinks = $this->_wink->countWinks();         $this->assertEquals(1, $numWinks, "wrong number of winks!");     } }
  • 21. Other Testing Strategies – Corner Cases Call functions under test with corner case inputs     - 0     - null     - ''           (an empty string)     - array()      (an empty array)     - Big numbers  (both positive & negative)     - Long strings     - Other large inputs (esp. where constants like MAX_SIZE are defined)
  • 22. Other Testing Strategies – Negative Testing Bad/illegal inputs should throw exceptions, raise errors, or otherwise alert the programmer of bad input // test that an exception is thrown try {     $result = tag_api::call('tagged.apps.gifts.getGiftRecipients', array('goldTxnId' => 0), $this->_userId);     $this->fail('getGiftRecipients did not throw an exception for invalid id'); } catch (Exception $e) {     $this->assertEquals(107, $e->code(), 'Wrong exception code'); } // test that an error is triggered $errorHandler = new testErrorHandler(); $errorHandler->suppressError('shared/class/tag/user/invites.php', E_USER_NOTICE); $result = $invites->removeOutgoingInvite($connectionId); $this->assertEquals(1,$errorHandler->numErrorsSuppressed(),'Notice not triggered'); $errorHandler->restorePreviousHandler();
  • 23. Other Testing Strategies – Differing Initial States Set up tests to begin with differing initial states // test that you can get a friend id from a user's friend list public function testGetRandomFriend() {     $friendList = array(34, 55, 88);     $friends = new Friends($friendList);     $randomFriend = $friends->getRandomFriend();     $this->assertTrue(in_array($randomFriend, $friendList), 'Got non-friend!'); } // test that you can't get a friend id when a user has no friends public function testGetRandomFriendWithNoFriends() {     $friendList = array();     $friends = new Friends($friendList);     $randomFriend = $friends->getRandomFriend();     $this->assertTrue(is_null($randomFriend), 'Got a friend from user with no friends!'); }
  • 24. Other Testing Strategies Tests should be as granular as possible -- each test should be its own function. // BAD $this->assertEquals(10, $objUnderTest->resultsPerPage()); // BETTER $this->assertEquals($objUnderTest::RESULTS_PER_PAGE, $objUnderTest->resultsPerPage()); Test assertions should be implementation-agnostic.  Changing the internal implementation of a method should not break the test. public function testAddAndRemoveFriend() {     $friendId = 54;     $friends = new Friends();     $friends->add($friendId);     $this->assertTrue($friends->isFriend($friendId));     // you should stop here, below this should be a separate test     $friends->remove($friendId);     $this->assertFalse($friends->isFriend($friendId)); }
  • 25. Test-Driven Development Stub out the methods for your class first, then write unit tests for that class. - At first, all tests will fail. - Write your class methods. - When all tests pass, you're done!   Also good for bug fixes. If you find a bug caused by unintended code behaviour,  write a test that asserts the correct behaviour.  When the test passes, the bug is fixed!
  • 26. Writing Testable Code Testing a unit code involves sealing off the “seams” with mock objects and canned results. Introduce seams in your code to help with testing: - Modularize methods - Use setters/getters - Pass objects to a class' constructor   The following common coding practices make testing very difficult: - Creating monolithic functions that handle more than one responsibility - Using global variables - Creating objects within methods instead of asking for them tag_email::send(new tag_email_options($userId, 'cafe_convertgold', $data));