5. PHPUnit Example
• Test Code
class StackTest extends PHPUnit_Framework_TestCase {
public function testPushAndPop() {
$stack = array();
$this->assertEquals(0, count($stack));
array_push($stack, 'foo');
$this->assertEquals('foo', $stack[count($stack)-1]);
$this->assertEquals(1, count($stack));
$this->assertEquals('foo', array_pop($stack));
$this->assertEquals(0, count($stack));
}
}
6. PHPUnit Test Cases Rule
• General Rule
1. The tests for a class Class go into a class ClassTest.
2. ClassTest inherits (most of the time) from
PHPUnit_Framework_TestCase.
3. The tests are public methods that are named test*.
4. Write Assertions
7. Data Provider
• Data Provider
– Return an iterative object (Iterator interface)
– Use for data-driven testing
• Like ACM Input data
– Use it carefully
8. Data Provider Sample
• Test Code
class DataTest extends PHPUnit_Framework_TestCase {
/**
* @dataProvider provider
*/
public function testAdd($a, $b, $c) {
$this->assertEquals($c, $a + $b);
}
public function provider() {
return array(
array(0, 0, 0),
array(0, 1, 1),
array(1, 0, 1),
array(1, 1, 3)
);
}
}
10. Testing Exception Sample
• Test Code
class ExceptionTest extends PHPUnit_Framework_TestCase {
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Right Message
*/
public function testExceptionHasRightMessage() {
throw new InvalidArgumentException('Some Message', 10);
}
/**
* @expectedException InvalidArgumentException
* @expectedExceptionCode 20
*/
public function testExceptionHasRightCode() {
throw new InvalidArgumentException('Some Message', 10);
}
}
11. Testing Exception Sample
• Test Code
class ExceptionTest extends PHPUnit_Framework_TestCase {
public function testExceptionHasRightMessage() {
$this->setExpectedException(
'InvalidArgumentException', 'Right Message'
);
throw new InvalidArgumentException('Some Message', 10);
}
public function testExceptionHasRightCode() {
$this->setExpectedException(
'InvalidArgumentException', 'Right Message', 20
);
throw new InvalidArgumentException(
'The Right Message', 10
);
}
}
12. Assertion
• Assertions
– assertEquals
– assertTrue / assertFalse
– assertContains
– and etc.
13. Assertion Guideline
• Assertion Guideline
– Using best suitable assertion
– Some assertions are more easy to use
• assertXmlFileEqualsXmlFile()
• assertRegExp()
• and etc.
– Make assertion contains useful message
14. Assertion Compare - Equals
• Test Code
class EqualTest extends PHPUnit_Framework_TestCase {
public function test_AssertTrue() {
$this->assertTrue("123" === "456");
}
public function test_AssertEquals() {
$this->assertEquals("123", "456");
}
}
15. Assertion Compare – Equals (cont.)
• Output
1) EqualTest::test_AssertTrue
Failed asserting that <boolean:false> is true.
/usr/home/hubert/tmp/php/equal_compare.php:6
2) EqualTest::test_AssertEquals
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-123
+456
/usr/home/hubert/tmp/php/equal_compare.php:10
16. Assertion Message
• Prototype
assertEmpty(mixed $actual[, string $message = ''])
• Test Code
class EqualTest extends PHPUnit_Framework_TestCase {
public function test_AssertMessage() {
$handler = new LogViewHandler();
$this->assertNotEmpty(
$handler->generate_ajax(),
"generate_ajax() should not be empty!!"
);
}
}
17. Assertion Message - Output
• Output
1) EqualTest::test_AssertMessage
generate_ajax() should not be empty!!
Failed asserting that a string is not empty.
/usr/home/hubert/tmp/php/equal_compare.php:24
18. xUnit Architecture
• Test Case
• Test fixtures
– Pre-action / Post-action needed to run a test
• Test Suites
– A set of tests that all share the same fixture
– The order of the tests shouldn't matter
19. Test Fixtures
• Fixtures
– Avoid duplicate Arrangement code
– Make test cases focus on Action and Assertion
• Test Fixtures
– setUp()
• Pre-action before each test case
– tearDown()
• Post-action after each test case
21. Fixture Example
• Test Code
class StackTest extends PHPUnit_Framework_TestCase {
protected $stack;
protected function setUp() {
$this->stack = array();
}
public function testEmpty() {
$this->assertTrue(empty($this->stack));
}
public function testPush() {
array_push($this->stack, 'foo');
$this->assertEquals('foo', $this->stack[count($this->stack)-1]);
$this->assertFalse(empty($this->stack));
}
public function testPop() {
array_push($this->stack, 'foo');
$this->assertEquals('foo', array_pop($this->stack));
$this->assertTrue(empty($this->stack));
}
}
22. Fixture Guideline
• Fixture Guideline
– Only use setUp and tearDown to initialize or
destroy objects that are shared throughout the
test class in all the tests
• Otherwise, readers don’t know which tests use the
logic inside the setup method and which don’t
23. Sharing Fixture
• Sharing Fixture
– Really few reason to share fixtures
– Good example
• Reuse database connection
– Sample Test Code
class DatabaseTest extends PHPUnit_Framework_TestCase {
protected static $dbh;
public static function setUpBeforeClass() {
self::$dbh = new PDO('sqlite::memory:');
}
public static function tearDownAfterClass() {
self::$dbh = NULL;
}
}
25. Execute PHPUnit tests
• Execute all tests
% phpunit
• Execute all tests in a subdirectory
% phpunit handlers
• Execute single test in a subdirectory
% phpunit --filter TMQLEscapeTest handlers
26. Test Naming
• Test Class Name
– For class name “Util”
– Test class name should be “UtilTest”
– Test filename should be “UtilTest.php”
27. Test Naming
• Function Name
– Test function name should be
test_<function>_<scenario>_<expect_behavior>
– Example
• test_escape_evenBackSlashesData_successEscape
28. Single Assertion / Concept per Test
• Single Assertion / Concept per Test
– If a test failed, the cause may be more obvious
– Compare
• PHPUnit Example
• Fixture Example
– testPushPop test 3 concepts
• Test for Empty / Push / Pop
29. Clean Test
• Clean Test
– Keeping Tests Clean
– Or you will not maintain them
– Test codes are as important code as production
– Write Test API / Utility / DSL
– Clean TDD cheat sheet
• http://www.planetgeek.ch/2011/01/04/clean-code-
and-clean-tdd-cheat-sheets/