Test in action week 2
-
Upload
yi-huan-chan -
Category
Technology
-
view
1.363 -
download
0
Transcript of Test in action week 2
![Page 1: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/1.jpg)
Test in Action – Week 2Testing Framework
Hubert Chan
![Page 2: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/2.jpg)
Testing Framework
• Why using framework?– Reinventing the wheel?– Frameworks provides• Library / API / Syntactic Sugar• xUnit Pattern• Stub / Mock• Log / Test Coverage• Static Analysis
![Page 3: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/3.jpg)
PHPUnit
• PHPUnit– Unit Testing Framework– Most common for PHP– Open Source– Used in known PHP Frameworks• Zend Framework• Kohana• symfony
![Page 4: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/4.jpg)
PHPUnit Installation
• Using pear– pear channel discover (only once)
pear channel-discover pear.phpunit.depear channel-discover components.ez.nopear channel-discover pear.symfony-project.com
– Install PHPUnitpear install phpunit/PHPUnit
![Page 5: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/5.jpg)
PHPUnit Example
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)); }}
• Test Code
![Page 6: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/6.jpg)
PHPUnit Test Cases Rule
• General Rule1. 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
![Page 7: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/7.jpg)
Data Provider
• Data Provider– Return an iterative object (Iterator interface)– Use for data-driven testing• Like ACM Input data
– Use it carefully
![Page 8: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/8.jpg)
Data Provider Sample
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) ); }}
• Test Code
![Page 9: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/9.jpg)
Testing Exception
• Testing Exception– Testing for failure cases– Error Handling– Examine• Exception Type• Exception Message• Exception Code
![Page 10: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/10.jpg)
Testing Exception Sample
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); }}
• Test Code
![Page 11: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/11.jpg)
Testing Exception Sample
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 ); }}
• Test Code
![Page 12: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/12.jpg)
Assertion
• Assertions– assertEquals– assertTrue / assertFalse– assertContains– and etc.
![Page 13: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/13.jpg)
Assertion Guideline
• Assertion Guideline– Using best suitable assertion– Some assertions are more easy to use• assertXmlFileEqualsXmlFile()• assertRegExp()• and etc.
– Make assertion contains useful message
![Page 14: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/14.jpg)
Assertion Compare - Equals
• Test Codeclass EqualTest extends PHPUnit_Framework_TestCase {
public function test_AssertTrue() { $this->assertTrue("123" === "456"); }
public function test_AssertEquals() { $this->assertEquals("123", "456"); }}
![Page 15: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/15.jpg)
Assertion Compare – Equals (cont.)
• Output• Output1) EqualTest::test_AssertTrueFailed asserting that <boolean:false> is true.
/usr/home/hubert/tmp/php/equal_compare.php:6
2) EqualTest::test_AssertEqualsFailed asserting that two strings are equal.--- Expected+++ Actual@@ @@-123+456
/usr/home/hubert/tmp/php/equal_compare.php:10
![Page 16: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/16.jpg)
Assertion Message
• Test Codeclass EqualTest extends PHPUnit_Framework_TestCase { public function test_AssertMessage() { $handler = new LogViewHandler(); $this->assertNotEmpty( $handler->generate_ajax(), "generate_ajax() should not be empty!!" ); }}
assertEmpty(mixed $actual[, string $message = ''])
• Prototype
![Page 17: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/17.jpg)
Assertion Message - Output
• Output1) EqualTest::test_AssertMessagegenerate_ajax() should not be empty!!Failed asserting that a string is not empty.
/usr/home/hubert/tmp/php/equal_compare.php:24
![Page 18: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/18.jpg)
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
![Page 19: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/19.jpg)
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
![Page 20: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/20.jpg)
Test Execution
![Page 21: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/21.jpg)
Fixture Example
• Test Codeclass 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)); }}
![Page 22: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/22.jpg)
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
![Page 23: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/23.jpg)
Sharing Fixture
• Sharing Fixture– Really few reason to share fixtures– Good example
• Reuse database connection
– Sample Test Codeclass 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; }}
![Page 24: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/24.jpg)
Organize PHPUnit Tests
• Mapping for production code and testtests|── _log|── bootstrap.php|── handlers│ └── _details│ |── TRConverterTest.php│ └── tmql│ └── TMQLEscapeTest.php|── lib└── phpunit.xml
middleware_rev |── handlers│ └── _details│ |── TRConverter.class.php│ └── tmql│ └── TMQLEscape.class.php└── lib
![Page 25: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/25.jpg)
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
![Page 26: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/26.jpg)
Test Naming
• Test Class Name– For class name “Util”– Test class name should be “UtilTest”– Test filename should be “UtilTest.php”
![Page 27: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/27.jpg)
Test Naming
• Function Name– Test function name should be
test_<function>_<scenario>_<expect_behavior>– Example• test_escape_evenBackSlashesData_successEscape
![Page 28: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/28.jpg)
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
![Page 29: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/29.jpg)
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/
![Page 30: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/30.jpg)
F.I.R.S.T
• F.I.R.S.T– Fast– Independent (isolated)– Repeatable– Self-Validating– Timely
![Page 31: Test in action week 2](https://reader035.fdocuments.us/reader035/viewer/2022062418/554d2aa4b4c905c5208b50b2/html5/thumbnails/31.jpg)
References
• Clean Code• The Art of Unit Testing