SlideShare a Scribd company logo
Unit Testing
By David Haskins
bool underAttack = false;
underAttack = detectEvents();
//do some other stuff
if(underAttack = true) {
launchNuclearMissles();
} else {
alert(“false alarm!”);
}
Why Test?
• Sometimes we make mistakes in our code
Why Test?
• Sometimes we make mistakes in our code
• Sometimes we forget to finish parts of our
code because we get interrupted, and then
we never come back and finish
Why Test?
• Sometimes we make mistakes in our code
• Sometimes we forget to finish parts of our
code because we get interrupted, and then
we never come back and finish
• //TODO: add another reason
Testing vs. Debugging
Testing: detecting errors
Debugging: diagnose and repair detected
errors
Types of testing
regression tests
functional tests
acceptance tests
integration tests
load/stress tests
security tests
unit tests
Unit Testing
Unit Testing: the execution of [code] that has
been written by a single programmer or team
of programmers, which is tested in isolation
from the more complete system.
- Code Complete 2nd ed.
How we end up testing stuff
class User{
public function __construct($userName){
//do stuff
}
public function checkPassword($password){
//do stuff
}
public function setLogIn(){
//do stuff
}
How we end up testing stuff
$u = new User(‘davidhaskins@ieee.org’);
//test to fail
$u->checkPassword(‘bad_password’);
//test to succeed
$u->checkPassword(‘s3kr3t_p@sswd’);
How we end up testing stuff
$u = new User(‘davidhaskins@ieee.org’);
//test to fail
if($u->checkPassword(‘bad_password’) === false){
echo ‘successfully rejected’;
}
//test to succeed
if($u->checkPassword(‘s3kr3t_p@sswd’) === true){
echo ‘successfully accepted’;
}
What do we do with this
information?
What do we do with this
information?
We delete it!!!
What do we do with this
information?
We delete it!!!
(or, at best, we comment it out)
Unit testing
PHPUnit
• a framework for unit testing PHP
• excellent documentation at http://phpunit.de
• easy to setup
Installing PHPUnit
• Pear
• Composer (preferred method)
Installing PHPUnit
pear config-set audto_discover 1
pear install pear.phpunit.de/PHPUnit
Installing PHPUnit
Composer can be used to download and install
“dependencies”(other libraries and such).
download composer:
curl -s http://getcomposer.org/installer | php
Installing PHPUnit
create a file named composer.json containing:
{
“require-dev”: {
“phpunit/phpunit”: “3.7.4”
}
}
Installing PHPUnit
run:
./composer.phar update
(a .phar file is a “PHP Archive” file.)
Installing PHPUnit
create a file named phpunit.xml containing:
<?xml version="1.0" encoding="UTF-8"?><phpunit
colors="true">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./phpUnitTutorial/Test/</directory>
</testsuite>
</testsuites></phpunit>
Running PHPUnit
./vendor/bin/phpunit
Running PHPUnit
./vendor/bin/phpunit
A simple PHPUnit test
class myTest extends PHPUnitTest_Framework_TestCase {
}
class myTest extends PHPUnitTest_Framework_TestCase {
public function someSimpleTest(){
}
}
class myTest extends PHPUnitTest_Framework_TestCase {
public function someSimpleTest(){
$myVar = true;
$this->assertTrue($myVar);
}
}
class myTest extends PHPUnitTest_Framework_TestCase {
public function someSimpleTest(){
$myVar = true;
$this->assertTrue($myVar);
}
public function anotherSimpleTest(){
$myVar = false;
$this->assertTrue($myvar); //fails
}
PHPUnit offers:
assertTrue();
assertFalse();
assertEquals();
assertArrayHasKey();
assertStringEndsWith();
...and many more!
The next few examples are
from Juan Treminio’s tutorial:
https://jtreminio.com/2013/03
The phrase “slugify” means to change
something like this:
The quick BROWN fox @ noon
into this:
the-quick-brown-fox-noon
<?phpclass URL
{
public function sluggify($string, $separator = '-', $maxLength = 96)
{
$title = iconv('UTF-8', 'ASCII//TRANSLIT', $string);
$title = preg_replace("%[^-/+|w ]%", '', $title);
$title = strtolower(trim(substr($title, 0, $maxLength), '-'));
$title = preg_replace("/[/_|+ -]+/", $separator, $title);
return $title;
}
}
Let’s write a test for it!
namespace phpUnitTutorialTest;use phpUnitTutorialURL;class
URLTest extends PHPUnit_Framework_TestCase
{
}
namespace phpUnitTutorialTest;use phpUnitTutorialURL;class
URLTest extends PHPUnit_Framework_TestCase
{
public function testSluggifyReturnsSluggifiedString()
{
$originalString = 'This string will be sluggified';
$expectedResult = 'this-string-will-be-sluggified';
}
}
namespace phpUnitTutorialTest;use phpUnitTutorialURL;class
URLTest extends PHPUnit_Framework_TestCase
{
public function testSluggifyReturnsSluggifiedString()
{
$originalString = 'This string will be sluggified';
$expectedResult = 'this-string-will-be-sluggified';
$url = new URL();
$result = $url->sluggify($originalString);
}
}
namespace phpUnitTutorialTest;use phpUnitTutorialURL;class
URLTest extends PHPUnit_Framework_TestCase
{
public function testSluggifyReturnsSluggifiedString()
{
$originalString = 'This string will be sluggified';
$expectedResult = 'this-string-will-be-sluggified';
$url = new URL();
$result = $url->sluggify($originalString);
$this->assertEquals($expectedResult, $result);
}
}
We have a unit test!
Other tests we can add
public function testSluggifyReturnsExpectedForStringsContainingNumbers() {
$originalString = 'This1 string2 will3 be 44 sluggified10';
$expectedResult = 'this1-string2-will3-be-44-sluggified10';
$url = new URL();
$result = $url->sluggify($originalString);
$this->assertEquals($expectedResult, $result);
}
Other tests we can add
public function testSluggifyReturnsExpectedForStringsContainingSpecialCharacters() {
$originalString = 'This! @string#$ %$will ()be "sluggified';
$expectedResult = 'this-string-will-be-sluggified';
$url = new URL();
$result = $url->sluggify($originalString);
$this->assertEquals($expectedResult, $result);
}
Other tests we can add
public function testSluggifyReturnsExpectedForStringsContainingNonEnglishCharacters() {
$originalString = "Tänk efter nu – förr'n vi föser dig bort";
$expectedResult = 'tank-efter-nu-forrn-vi-foser-dig-bort';
$url = new URL();
$result = $url->sluggify($originalString);
$this->assertEquals($expectedResult, $result);
}
Other tests we can add
public function testSluggifyReturnsExpectedForEmptyStrings() {
$originalString = '';
$expectedResult = '';
$url = new URL();
$result = $url->sluggify($originalString);
$this->assertEquals($expectedResult, $result);
}
Unit testing
That’s neat, but it seems we are writing the
same code over and over.
That’s neat, but it seems we are writing the
same code over and over.
We can use the “dataProvider annotation.”
That’s neat, but it seems we are writing the
same code over and over.
We can use the “dataProvider annotation.”
Annotations are described in docblocks
(comments) of methods.
class URLTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider providerTestSluggifyReturnsSluggifiedString
*/
public function testSluggifyReturnsSluggifiedString($originalString, $expectedResult)
{
//do our assertion here
}
public function providerTestSluggifyReturnsSluggifiedString()
{
//return an array of arrays which contains our data
}
}
class URLTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider providerTestSluggifyReturnsSluggifiedString
*/
public function testSluggifyReturnsSluggifiedString($originalString, $expectedResult)
{
$url = new URL();
$result = $url->sluggify($originalString);
$this->assertEquals($expectedResult, $result);
}
public function providerTestSluggifyReturnsSluggifiedString()
{
return array(
array('This string will be sluggified', 'this-string-will-be-sluggified'),
array('THIS STRING WILL BE SLUGGIFIED', 'this-string-will-be-sluggified'),
array('This1 string2 will3 be 44 sluggified10', 'this1-string2-will3-be-44-sluggified10'),
array('This! @string#$ %$will ()be "sluggified', 'this-string-will-be-sluggified'),
array("Tänk efter nu – förr'n vi föser dig bort", 'tank-efter-nu-forrn-vi-foser-dig-bort'),
array('', ''),
);
}
}
I haven’t been honest here
URL::Sluggify() was deceptively simple it; had
no dependencies.
When you're doing testing like this, you're focusing on one
element of the software at a time -hence the common
term unit testing. The problem is that to make a single
unit work, you often need other units...
- Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html
What happens when we depend on other stuff
(databases, other objects, etc.)?
setUp() and tearDown()
class FoobarTest extends PHPUnit_Framework_Testcase{
public function setUp(){
//do things before these tests run
// copy a production database into a test db
// instantiate objects
// define constants
}
public function tearDown(){
//do things after the tests run
// delete test db
}
}
But we still have problems
Databases can go down which could cause our
tests to fail.
Instantiating objects can be slow which could
make testing take forever (we want to be able
to test often).
...and we want isolation!
“Mocks and stubs” to the rescue!
We may have to jump through some hoops, but
we’ll get there!
Stubs
//a method with stuff (implementation details irrelevant)
public function doSomething($param1, $param2){
mysql_connect("your.hostaddress.com", $param1, $param2) or
die(mysql_error());
mysql_select_db("address") or die(mysql_error());
!(isset($pagenum)) ? $pagenum = 1 : $pagenum=0;
$data = mysql_query("SELECT * FROM topsites") or die(mysql_error());
$rows = mysql_num_rows($data);
$page_rows = 4;
$last = ceil($rows/$page_rows);
$pagenum < 1 ? $pagenum=1 : $pagenum = $last;
$max = 'limit ' .($pagenum - 1) * $page_rows .',' .$page_rows;
return $max;
}
Stubs
//a method with stuff (implementation details irrelevant)
public function StubDoSomething($param1, $param2){
return null;
}
Mock objects
Mock Objects: objects pre-programmed with
expectations which form a specification of the
calls they are expected to receive.
Mock objects
Let’s look at an example.
Mock objects
class User{
public function __construct($id){
$this-> id = $id;
}
public function verifyUser(){
//validate against an LDAP server
}
public function getName(){
//get user name from the LDAP server
}
Mock objects
class ForumPost{
public function deletePostsByUser($user){
$user_id = $user->getUserID();
$query = “delete from posts where userID = ? ”;
….//do stuff
}
//...other methods
}
require_once ‘User.php’;
require_once ‘ForumPost.php’;
class testForum extends PHPUnitTest_Framework_TestCase {
public function testUserPostDelete(){
$user = new User(7);
$userName = $user->getName();
$post = new ForumPost();
$rowsDeleted = $post->deletePostsByUser($user);
$message = “$rowsDeleted posts removed for $userName”;
$expectedMessage = “5 posts removed for David Haskins”;
$this->assertEquals($message,$expectedMessage);
}
}
require_once ‘User.php’;
require_once ‘ForumPost.php’;
class testForum extends PHPUnitTest_Framework_TestCase {
public function testUserPostDelete(){
$user = new User(7); //fails when LDAP server is down!
$userName = $user->getName();
$post = new ForumPost();
$rowsDeleted = $post->deletePostsByUser($user);
$message = “$rowsDeleted posts removed for $userName”;
$expectedMessage = “5 posts removed for David Haskins”;
$this->assertEquals($message,$expectedMessage);
}
}
require_once ‘User.php’;
require_once ‘ForumPost.php’;
class testForum extends PHPUnitTest_Framework_TestCase {
public function testUserPostDelete(){
$user = $this->getMockBuilder(‘User’)
->setConstructorArgs(array(7))
->getMock();
$user->expects($this->once())
->method(‘getName’)
->will($this->returnValue(‘David Haskins’);
$userName = $user->getName();
$post = new ForumPost();
$rowsDeleted = $post->deletePostsByUser($user);
$message = “$rowsDeleted posts removed for $userName”;
$expectedMessage = “5 posts removed for David Haskins”;
$this->assertEquals($message,$expectedMessage);
}
Unit testing
TDD
Test Driven Development is a method of
developing code by writing the tests FIRST!
TDD
Git and unit tests
You can add client or server side “hooks” to git
to run your unit tests and reject submissions
that fail the unit tests.
http://www.masnun.com/2012/03/18/running-phpunit-on-git-hook.html
Coverage report tool
./vendor/bin/phpunit --coverage-html coverage
bool underAttack = false;
underAttack = detectEvents();
//do some other stuff
if(underAttack = true) {
launchNuclearMissles();
} else {
alert(“false alarm!”);
}
Other Texts to Consider
https://jtreminio.com/2013/03
http://phpunit.de

More Related Content

PDF
Unit testing PHP apps with PHPUnit
PDF
Unit testing with PHPUnit - there's life outside of TDD
KEY
DjangoCon US 2011 - Monkeying around at New Relic
PDF
Workshop quality assurance for php projects - ZendCon 2013
PDF
UA testing with Selenium and PHPUnit - PFCongres 2013
PDF
Spock: Test Well and Prosper
PDF
Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.
PPTX
Automation patterns on practice
Unit testing PHP apps with PHPUnit
Unit testing with PHPUnit - there's life outside of TDD
DjangoCon US 2011 - Monkeying around at New Relic
Workshop quality assurance for php projects - ZendCon 2013
UA testing with Selenium and PHPUnit - PFCongres 2013
Spock: Test Well and Prosper
Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.
Automation patterns on practice

What's hot (20)

PPTX
Smarter Testing With Spock
PDF
PDF
We Are All Testers Now: The Testing Pyramid and Front-End Development
PDF
Spock: A Highly Logical Way To Test
PPTX
Spring & Hibernate
PPT
Unit testing with Spock Framework
PDF
Spock Testing Framework - The Next Generation
PDF
Software Testing - Invited Lecture at UNSW Sydney
PDF
Javascript TDD with Jasmine, Karma, and Gulp
PPTX
Jdk 7 4-forkjoin
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
PDF
Java 7 LavaJUG
PPTX
Smarter Testing with Spock
PPT
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
DOCX
201913046 wahyu septiansyah network programing
PDF
Redux for ReactJS Programmers
PPTX
Building unit tests correctly
PDF
Spock framework
PDF
PDF
Refactoring In Tdd The Missing Part
Smarter Testing With Spock
We Are All Testers Now: The Testing Pyramid and Front-End Development
Spock: A Highly Logical Way To Test
Spring & Hibernate
Unit testing with Spock Framework
Spock Testing Framework - The Next Generation
Software Testing - Invited Lecture at UNSW Sydney
Javascript TDD with Jasmine, Karma, and Gulp
Jdk 7 4-forkjoin
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 LavaJUG
Smarter Testing with Spock
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
201913046 wahyu septiansyah network programing
Redux for ReactJS Programmers
Building unit tests correctly
Spock framework
Refactoring In Tdd The Missing Part
Ad

Viewers also liked (6)

PPTX
Quatorze juillet
PDF
Togaf v9-m3-intro-adm
PPTX
Web security
PPTX
Agile development
PDF
Togaf v9-m2-togaf9-components
PDF
Quatorze juillet
Togaf v9-m3-intro-adm
Web security
Agile development
Togaf v9-m2-togaf9-components
Ad

Similar to Unit testing (20)

PDF
Fighting Fear-Driven-Development With PHPUnit
PPT
Automated Unit Testing
PDF
Writing Swift code with great testability
PPT
Phpunit testing
KEY
Workshop quality assurance for php projects tek12
PPTX
Unit Testing in PHP
PPT
Test Driven Development with PHPUnit
PDF
Getting started with TDD - Confoo 2014
PDF
Quality Assurance for PHP projects - ZendCon 2012
PPT
Testing And Drupal
PPTX
NodeJs
PPT
Zend Framework 2 - PHPUnit
PPT
Unit Testing using PHPUnit
ODP
Bring the fun back to java
PPTX
Code igniter unittest-part1
PDF
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
PDF
Commencer avec le TDD
PDF
Unit testing for WordPress
ODP
Grails unit testing
PDF
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Fighting Fear-Driven-Development With PHPUnit
Automated Unit Testing
Writing Swift code with great testability
Phpunit testing
Workshop quality assurance for php projects tek12
Unit Testing in PHP
Test Driven Development with PHPUnit
Getting started with TDD - Confoo 2014
Quality Assurance for PHP projects - ZendCon 2012
Testing And Drupal
NodeJs
Zend Framework 2 - PHPUnit
Unit Testing using PHPUnit
Bring the fun back to java
Code igniter unittest-part1
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
Commencer avec le TDD
Unit testing for WordPress
Grails unit testing
EPHPC Webinar Slides: Unit Testing by Arthur Purnama

Recently uploaded (20)

PDF
Insiders guide to clinical Medicine.pdf
PDF
Sports Quiz easy sports quiz sports quiz
PDF
Basic Mud Logging Guide for educational purpose
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PDF
Module 4: Burden of Disease Tutorial Slides S2 2025
PDF
STATICS OF THE RIGID BODIES Hibbelers.pdf
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PPTX
Institutional Correction lecture only . . .
PPTX
Cell Types and Its function , kingdom of life
PDF
Saundersa Comprehensive Review for the NCLEX-RN Examination.pdf
PDF
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PPTX
Cell Structure & Organelles in detailed.
PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
PDF
Classroom Observation Tools for Teachers
PDF
Computing-Curriculum for Schools in Ghana
Insiders guide to clinical Medicine.pdf
Sports Quiz easy sports quiz sports quiz
Basic Mud Logging Guide for educational purpose
FourierSeries-QuestionsWithAnswers(Part-A).pdf
Final Presentation General Medicine 03-08-2024.pptx
Module 4: Burden of Disease Tutorial Slides S2 2025
STATICS OF THE RIGID BODIES Hibbelers.pdf
Abdominal Access Techniques with Prof. Dr. R K Mishra
O5-L3 Freight Transport Ops (International) V1.pdf
Institutional Correction lecture only . . .
Cell Types and Its function , kingdom of life
Saundersa Comprehensive Review for the NCLEX-RN Examination.pdf
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
O7-L3 Supply Chain Operations - ICLT Program
102 student loan defaulters named and shamed – Is someone you know on the list?
Renaissance Architecture: A Journey from Faith to Humanism
Cell Structure & Organelles in detailed.
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
Classroom Observation Tools for Teachers
Computing-Curriculum for Schools in Ghana

Unit testing

  • 2. bool underAttack = false; underAttack = detectEvents(); //do some other stuff if(underAttack = true) { launchNuclearMissles(); } else { alert(“false alarm!”); }
  • 3. Why Test? • Sometimes we make mistakes in our code
  • 4. Why Test? • Sometimes we make mistakes in our code • Sometimes we forget to finish parts of our code because we get interrupted, and then we never come back and finish
  • 5. Why Test? • Sometimes we make mistakes in our code • Sometimes we forget to finish parts of our code because we get interrupted, and then we never come back and finish • //TODO: add another reason
  • 6. Testing vs. Debugging Testing: detecting errors Debugging: diagnose and repair detected errors
  • 7. Types of testing regression tests functional tests acceptance tests integration tests load/stress tests security tests unit tests
  • 8. Unit Testing Unit Testing: the execution of [code] that has been written by a single programmer or team of programmers, which is tested in isolation from the more complete system. - Code Complete 2nd ed.
  • 9. How we end up testing stuff class User{ public function __construct($userName){ //do stuff } public function checkPassword($password){ //do stuff } public function setLogIn(){ //do stuff }
  • 10. How we end up testing stuff $u = new User(‘davidhaskins@ieee.org’); //test to fail $u->checkPassword(‘bad_password’); //test to succeed $u->checkPassword(‘s3kr3t_p@sswd’);
  • 11. How we end up testing stuff $u = new User(‘davidhaskins@ieee.org’); //test to fail if($u->checkPassword(‘bad_password’) === false){ echo ‘successfully rejected’; } //test to succeed if($u->checkPassword(‘s3kr3t_p@sswd’) === true){ echo ‘successfully accepted’; }
  • 12. What do we do with this information?
  • 13. What do we do with this information? We delete it!!!
  • 14. What do we do with this information? We delete it!!! (or, at best, we comment it out)
  • 16. PHPUnit • a framework for unit testing PHP • excellent documentation at http://phpunit.de • easy to setup
  • 17. Installing PHPUnit • Pear • Composer (preferred method)
  • 18. Installing PHPUnit pear config-set audto_discover 1 pear install pear.phpunit.de/PHPUnit
  • 19. Installing PHPUnit Composer can be used to download and install “dependencies”(other libraries and such). download composer: curl -s http://getcomposer.org/installer | php
  • 20. Installing PHPUnit create a file named composer.json containing: { “require-dev”: { “phpunit/phpunit”: “3.7.4” } }
  • 21. Installing PHPUnit run: ./composer.phar update (a .phar file is a “PHP Archive” file.)
  • 22. Installing PHPUnit create a file named phpunit.xml containing: <?xml version="1.0" encoding="UTF-8"?><phpunit colors="true"> <testsuites> <testsuite name="Application Test Suite"> <directory>./phpUnitTutorial/Test/</directory> </testsuite> </testsuites></phpunit>
  • 26. class myTest extends PHPUnitTest_Framework_TestCase { }
  • 27. class myTest extends PHPUnitTest_Framework_TestCase { public function someSimpleTest(){ } }
  • 28. class myTest extends PHPUnitTest_Framework_TestCase { public function someSimpleTest(){ $myVar = true; $this->assertTrue($myVar); } }
  • 29. class myTest extends PHPUnitTest_Framework_TestCase { public function someSimpleTest(){ $myVar = true; $this->assertTrue($myVar); } public function anotherSimpleTest(){ $myVar = false; $this->assertTrue($myvar); //fails }
  • 31. The next few examples are from Juan Treminio’s tutorial: https://jtreminio.com/2013/03
  • 32. The phrase “slugify” means to change something like this: The quick BROWN fox @ noon into this: the-quick-brown-fox-noon
  • 33. <?phpclass URL { public function sluggify($string, $separator = '-', $maxLength = 96) { $title = iconv('UTF-8', 'ASCII//TRANSLIT', $string); $title = preg_replace("%[^-/+|w ]%", '', $title); $title = strtolower(trim(substr($title, 0, $maxLength), '-')); $title = preg_replace("/[/_|+ -]+/", $separator, $title); return $title; } }
  • 34. Let’s write a test for it!
  • 36. namespace phpUnitTutorialTest;use phpUnitTutorialURL;class URLTest extends PHPUnit_Framework_TestCase { public function testSluggifyReturnsSluggifiedString() { $originalString = 'This string will be sluggified'; $expectedResult = 'this-string-will-be-sluggified'; } }
  • 37. namespace phpUnitTutorialTest;use phpUnitTutorialURL;class URLTest extends PHPUnit_Framework_TestCase { public function testSluggifyReturnsSluggifiedString() { $originalString = 'This string will be sluggified'; $expectedResult = 'this-string-will-be-sluggified'; $url = new URL(); $result = $url->sluggify($originalString); } }
  • 38. namespace phpUnitTutorialTest;use phpUnitTutorialURL;class URLTest extends PHPUnit_Framework_TestCase { public function testSluggifyReturnsSluggifiedString() { $originalString = 'This string will be sluggified'; $expectedResult = 'this-string-will-be-sluggified'; $url = new URL(); $result = $url->sluggify($originalString); $this->assertEquals($expectedResult, $result); } }
  • 39. We have a unit test!
  • 40. Other tests we can add public function testSluggifyReturnsExpectedForStringsContainingNumbers() { $originalString = 'This1 string2 will3 be 44 sluggified10'; $expectedResult = 'this1-string2-will3-be-44-sluggified10'; $url = new URL(); $result = $url->sluggify($originalString); $this->assertEquals($expectedResult, $result); }
  • 41. Other tests we can add public function testSluggifyReturnsExpectedForStringsContainingSpecialCharacters() { $originalString = 'This! @string#$ %$will ()be "sluggified'; $expectedResult = 'this-string-will-be-sluggified'; $url = new URL(); $result = $url->sluggify($originalString); $this->assertEquals($expectedResult, $result); }
  • 42. Other tests we can add public function testSluggifyReturnsExpectedForStringsContainingNonEnglishCharacters() { $originalString = "Tänk efter nu – förr'n vi föser dig bort"; $expectedResult = 'tank-efter-nu-forrn-vi-foser-dig-bort'; $url = new URL(); $result = $url->sluggify($originalString); $this->assertEquals($expectedResult, $result); }
  • 43. Other tests we can add public function testSluggifyReturnsExpectedForEmptyStrings() { $originalString = ''; $expectedResult = ''; $url = new URL(); $result = $url->sluggify($originalString); $this->assertEquals($expectedResult, $result); }
  • 45. That’s neat, but it seems we are writing the same code over and over.
  • 46. That’s neat, but it seems we are writing the same code over and over. We can use the “dataProvider annotation.”
  • 47. That’s neat, but it seems we are writing the same code over and over. We can use the “dataProvider annotation.” Annotations are described in docblocks (comments) of methods.
  • 48. class URLTest extends PHPUnit_Framework_TestCase { /** * @dataProvider providerTestSluggifyReturnsSluggifiedString */ public function testSluggifyReturnsSluggifiedString($originalString, $expectedResult) { //do our assertion here } public function providerTestSluggifyReturnsSluggifiedString() { //return an array of arrays which contains our data } }
  • 49. class URLTest extends PHPUnit_Framework_TestCase { /** * @dataProvider providerTestSluggifyReturnsSluggifiedString */ public function testSluggifyReturnsSluggifiedString($originalString, $expectedResult) { $url = new URL(); $result = $url->sluggify($originalString); $this->assertEquals($expectedResult, $result); } public function providerTestSluggifyReturnsSluggifiedString() { return array( array('This string will be sluggified', 'this-string-will-be-sluggified'), array('THIS STRING WILL BE SLUGGIFIED', 'this-string-will-be-sluggified'), array('This1 string2 will3 be 44 sluggified10', 'this1-string2-will3-be-44-sluggified10'), array('This! @string#$ %$will ()be "sluggified', 'this-string-will-be-sluggified'), array("Tänk efter nu – förr'n vi föser dig bort", 'tank-efter-nu-forrn-vi-foser-dig-bort'), array('', ''), ); } }
  • 50. I haven’t been honest here URL::Sluggify() was deceptively simple it; had no dependencies.
  • 51. When you're doing testing like this, you're focusing on one element of the software at a time -hence the common term unit testing. The problem is that to make a single unit work, you often need other units... - Martin Fowler http://martinfowler.com/articles/mocksArentStubs.html
  • 52. What happens when we depend on other stuff (databases, other objects, etc.)?
  • 53. setUp() and tearDown() class FoobarTest extends PHPUnit_Framework_Testcase{ public function setUp(){ //do things before these tests run // copy a production database into a test db // instantiate objects // define constants } public function tearDown(){ //do things after the tests run // delete test db } }
  • 54. But we still have problems Databases can go down which could cause our tests to fail. Instantiating objects can be slow which could make testing take forever (we want to be able to test often). ...and we want isolation!
  • 55. “Mocks and stubs” to the rescue!
  • 56. We may have to jump through some hoops, but we’ll get there!
  • 57. Stubs //a method with stuff (implementation details irrelevant) public function doSomething($param1, $param2){ mysql_connect("your.hostaddress.com", $param1, $param2) or die(mysql_error()); mysql_select_db("address") or die(mysql_error()); !(isset($pagenum)) ? $pagenum = 1 : $pagenum=0; $data = mysql_query("SELECT * FROM topsites") or die(mysql_error()); $rows = mysql_num_rows($data); $page_rows = 4; $last = ceil($rows/$page_rows); $pagenum < 1 ? $pagenum=1 : $pagenum = $last; $max = 'limit ' .($pagenum - 1) * $page_rows .',' .$page_rows; return $max; }
  • 58. Stubs //a method with stuff (implementation details irrelevant) public function StubDoSomething($param1, $param2){ return null; }
  • 59. Mock objects Mock Objects: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
  • 60. Mock objects Let’s look at an example.
  • 61. Mock objects class User{ public function __construct($id){ $this-> id = $id; } public function verifyUser(){ //validate against an LDAP server } public function getName(){ //get user name from the LDAP server }
  • 62. Mock objects class ForumPost{ public function deletePostsByUser($user){ $user_id = $user->getUserID(); $query = “delete from posts where userID = ? ”; ….//do stuff } //...other methods }
  • 63. require_once ‘User.php’; require_once ‘ForumPost.php’; class testForum extends PHPUnitTest_Framework_TestCase { public function testUserPostDelete(){ $user = new User(7); $userName = $user->getName(); $post = new ForumPost(); $rowsDeleted = $post->deletePostsByUser($user); $message = “$rowsDeleted posts removed for $userName”; $expectedMessage = “5 posts removed for David Haskins”; $this->assertEquals($message,$expectedMessage); } }
  • 64. require_once ‘User.php’; require_once ‘ForumPost.php’; class testForum extends PHPUnitTest_Framework_TestCase { public function testUserPostDelete(){ $user = new User(7); //fails when LDAP server is down! $userName = $user->getName(); $post = new ForumPost(); $rowsDeleted = $post->deletePostsByUser($user); $message = “$rowsDeleted posts removed for $userName”; $expectedMessage = “5 posts removed for David Haskins”; $this->assertEquals($message,$expectedMessage); } }
  • 65. require_once ‘User.php’; require_once ‘ForumPost.php’; class testForum extends PHPUnitTest_Framework_TestCase { public function testUserPostDelete(){ $user = $this->getMockBuilder(‘User’) ->setConstructorArgs(array(7)) ->getMock(); $user->expects($this->once()) ->method(‘getName’) ->will($this->returnValue(‘David Haskins’); $userName = $user->getName(); $post = new ForumPost(); $rowsDeleted = $post->deletePostsByUser($user); $message = “$rowsDeleted posts removed for $userName”; $expectedMessage = “5 posts removed for David Haskins”; $this->assertEquals($message,$expectedMessage); }
  • 67. TDD Test Driven Development is a method of developing code by writing the tests FIRST!
  • 68. TDD
  • 69. Git and unit tests You can add client or server side “hooks” to git to run your unit tests and reject submissions that fail the unit tests. http://www.masnun.com/2012/03/18/running-phpunit-on-git-hook.html
  • 70. Coverage report tool ./vendor/bin/phpunit --coverage-html coverage
  • 71. bool underAttack = false; underAttack = detectEvents(); //do some other stuff if(underAttack = true) { launchNuclearMissles(); } else { alert(“false alarm!”); }
  • 72. Other Texts to Consider https://jtreminio.com/2013/03 http://phpunit.de

Editor's Notes

  • #16: But what if we could use it?! (Eureka! Archimedes reference)