phpunit入门 r2

36
PHPUnit 入入 PHP User Group Shanghai 2008- 04-26 Zhou Xianhua BaohuaCai PHP User Group Shanghai 2008 1

Upload: baohua-cai

Post on 17-May-2015

1.560 views

Category:

Documents


11 download

TRANSCRIPT

Page 1: Phpunit入门 r2

PHPUnit入门

PHP User Group Shanghai 2008-04-26

Zhou XianhuaBaohuaCai

PHP User Group Shanghai 2008

1

Page 2: Phpunit入门 r2

测试?

• 测试方法– 黑盒测试– 白盒测试

• 测试过程– 单元测试– 集成测试– 压力测试– 并发测试– 环境测试

PHP User Group Shanghai 2008

2

Page 3: Phpunit入门 r2

为什么要进行单元测试?

• 保证代码按照特定的行为运行• 减少 Bug• 提高整体项目开发效率• 便于项目后续的维护

PHP User Group Shanghai 2008

3

Page 4: Phpunit入门 r2

常见的测试工具• PHP

– PHPUnit、 SimpleTest• ActionScript

– AsUnit• Javascript

– JsUnit、 scriptaculous(unittest)、 crosscheck

• Java– Junit、 TestNG

• Python– PyUnit

PHP User Group Shanghai 2008

4

Page 5: Phpunit入门 r2

PHPUnit的特性• 安装、使用方便,是 xUnit家族中的一员• 完全支持 PHP5• 开源、免费、有详细的文档供参考及官方支持• 提供多种格式的测试输出( XML、 JSON、 TAP...)

• 可以自动生成测试类( --skeleton)及从测试类生成应用类

• 提供 Selenium RC 接口,便于在真实的浏览器中测试,实现基于WEB的功能测试。

• 参考: http://www.phpunit.de/wiki/Features

PHP User Group Shanghai 2008

5

Page 6: Phpunit入门 r2

安装 PHPUnit

• 使用 PEAR安装– pear channel-discover pear.phpunit.de– pear install phpunit/PHPUnit

• 直接下载压缩包(或从 svn库导出)– http://pear.phpunit.de/get/PHPUnit-3.2.18.tgz– 在 php.ini中设置 include_path,包含 PHPUnit路径

– 把 pear-phpunit改名为 phpunit,并加上可执行属性,把文件中的@php_bin@改成 php可执行命令所在的路径(注:Win下是 pear-phpunit.bat)

– 修改 PHPUnit/Util/Fileloader.php,把文件中的@php_bin@改成 php可执行命令所在的路径

PHP User Group Shanghai 2008

6

Page 7: Phpunit入门 r2

安装成功

运行 phpunit– PHPUnit 3.2.18 by Sebastian Bergmann.– Usage: phpunit [switches] UnitTest

[UnitTest.php]– --log-json Log test execution in JSON

format.– --log-tapLog test execution in TAP format

to file.– --log-xml Logtest execution in XML

PHP User Group Shanghai 2008

7

Page 8: Phpunit入门 r2

传统的测试// 测试输入的用户名是否合法function checkName($name){ return (bool)preg_match('/^[\w_\d]{3,30}$/',

$name);}// 传统的测试方法echo checkName(”testUserName”) ? ”Y” : ”N”;var_dump(checkName(” ”));if(checkName(”......”)) echo ”...”;

Page 9: Phpunit入门 r2

第一个 PHPUnit测试// CheckNameTest.phprequire_once 'PHPUnit/Framework.php';require_once 'checkName.php';

class CheckNameTest extends PHPUnit_Framework_TestCase{ public function testValidateUser() { $this->assertTrue(checkName(”testUser001”)); $this->assertFalse(checkName(”User 001”)); }}

Page 10: Phpunit入门 r2

运行第一个 PHPUnit测试

$phpunit CheckNameTest.php

PHPUnit 3.2.18 by Sebastian Bergmann.

Time: 0 seconds

OK (1 test)

Page 11: Phpunit入门 r2

测试步骤1. 将类 Class的测试写入 ClassTest2. ClassTest继承(通常)自

PHPUnit_Framework_TestCase3. 测试都是公用方法,命名为 test*4. 在测试方法中,类似 assertEquals()的断言方法用来断言一个实际值(应该)匹配一个期望值

Page 12: Phpunit入门 r2

数据提供者class DataTest extends PHPUnit_Framework_TestCase{    

public static function provider()    {        return array(

array(1, 0, 1),array(1, 1, 3)

);     }     

/* @dataProvider provider     */    public function testAdd($a, $b, $c)  {        

$this->assertEquals($c, $a + $b);    }

}

Page 13: Phpunit入门 r2

含有通过和失败的测试require_once 'PHPUnit/Framework.php';class MyTest extends

PHPUnit_Framework_TestCase { public function testSuccess() { $this->assertEquals(3, 1 + 2); }

public function testFailure() { $this->assertTrue(2 > 3); }}

Page 14: Phpunit入门 r2

含有通过和失败的测试结果

.FTime: 0 seconds

There was 1 failure:

1) testFailure(MyTest)Failed asserting that <boolean:false> is true./home/zhouxh/php/phpunit/MyTest.php:11

FAILURES!Tests: 2, Failures: 1

Page 15: Phpunit入门 r2

不同的测试结果. 测试成功输出F 测试当中断言失败时输出E 测试有错误发生时输出S 测试被跳过时输出I 测试未完成时输出

Page 16: Phpunit入门 r2

有错误发生的测试( E)public function testError() {

$this->assertLessThan(3);$this->assertEquals(”E?”);

}---------E1) testFailure(MyTest)Missing argument 2 for

PHPUnit_Framework_Assert::assertLessThan(), called in ... ...

Page 17: Phpunit入门 r2

被跳过的测试( S)public function testSkip() { $this->markTestSkipped("Skipped test!"); // stop!!! $this->assertTrue(true);}---$phpunit –verbose MyTest.phpS...1) testSkip(MyTest)Skipped test!...

Page 18: Phpunit入门 r2

未完成的测试( I)public function testIncomplete() { $this->markTestIncomplete("Incomplete test!"); // stop!!! $this->assertTrue(true);}---$phpunit –verbose MyTest.phpI...1) testIncomplete(MyTest)Incomplete test!...

Page 19: Phpunit入门 r2

夹具 (Fixtures)class MyTest extends PHPUnit_Framework_TestCase { public function setUp() { $this->mysqlConnection = mysql_connection(”localhost”,

”root”, ”password”); $this->data = array(1, 2, 3, 4); }

public function testOne() {} public function testTwo() {}

public function tearDown() { mysql_close($this->mysqlConnection); unset($this->data); }}

Page 20: Phpunit入门 r2

夹具 (Fixtures)

setUp()testOne()

tearDown()

setUp()testTwo()

tearDown()

Page 21: Phpunit入门 r2

同时测试多个文件// AllTests.phprequire_once 'PHPUnit/Framework.php';require_once 'PHPUnit/TextUI/TestRunner.php';

$suite = new PHPUnit_Framework_TestSuite();$suite->addTestFile('tests/CheckNameTest.php');$suite->addTestFile('tests/CheckPasswordTest.php');

PHPUnit_TextUI_TestRunner::run($suite);---$php AllTests.php...

Page 22: Phpunit入门 r2

同时测试多个文件// AllTests.phprequire_once 'PHPUnit/Framework.php';require_once 'PHPUnit/TextUI/TestRunner.php';

require_once 'tests/CheckNameTest.php';require_once 'tests/CheckPasswordTest.php';

$suite = new PHPUnit_Framework_TestSuite();$suite->addTestSuite('CheckNameTest');$suite->addTestSuite('CheckPasswordTest');

PHPUnit_TextUI_TestRunner::run($suite);

Page 23: Phpunit入门 r2

输出测试require "PHPUnit/Extensions/OutputTestCase.php";

class OutputTest extends PHPUnit_Extensions_OutputTestCase {

public function testOne() { $this->expectOutputString("php"); echo "php"; } public function testTwo() { $this->expectOutputString("phd"); echo "php"; }}

Page 24: Phpunit入门 r2

输出测试结果.F

Time: 0 seconds

There was 1 failure:

1) testTwo(OutputTest)Failed asserting that two strings are equal.expected string <phd>difference < x>got string <php>

Tests: 2, Failures: 1.

Page 25: Phpunit入门 r2

性能测试require_once 'PHPUnit/Extensions/PerformanceTestCase.php'; class PerformanceTest extends PHPUnit_Extensions_PerformanceTestCase{ public function testPerformance() { $this->setMaxRunningTime(2); sleep(1); }}

Page 26: Phpunit入门 r2

其它扩展测试

• 数据库测试– PHPUnit_Extensions_Database_TestCase

• PHP格式测试– PHPUnit_Extensions_PhptTestCase– http://qa.php.net/write-test.php

• Selenium Rc测试– PHPUnit_Extensions_SeleniumTestCase– http://selenium.openqa.org/

Page 27: Phpunit入门 r2

测试驱动开发 (TDD)

• 主要开发步骤– 1.编写测试用例– 2.运行测试用例(此时测试结果必然是失败的)– 3.为测试用例编写代码– 4.再次运行测试用例(测试结果是成功或失败的)若失败则返回第 3步继续。

– 5.根据需要清除 /优化相关代码(重构),收工 !

Test Code Test Code

Page 28: Phpunit入门 r2

测试驱动开发 (TDD):例子require_once 'PHPUnit/Framework.php';require_once 'Cal.php';class MyTest extends PHPUnit_Framework_TestCase { protected $cal; protected function setUp() { $this->cal = new Cal(); } public function testAdd() { $this->assertEquals(3, $this->cal->add(1, 2)); } public function tearDown() { $this->cal = null; }}

Page 29: Phpunit入门 r2

测试驱动开发 (TDD):例子

$phpunit MyTest.php

Fatal error: require_once(): Failed opening required 'Cal.php' (include_path='.:

... ...

Page 30: Phpunit入门 r2

测试驱动开发 (TDD):例子

class Cal { public function add() { }}

Page 31: Phpunit入门 r2

测试驱动开发 (TDD):例子phpunit MyTest.php

F

Time: 0 seconds

There was 1 failure:

1) testAdd(MyTest)Failed asserting that <null> matches expected value

<integer:3>.

Page 32: Phpunit入门 r2

测试驱动开发 (TDD):例子

class Cal { public function add($a, $b) { return $a + $b; }}

Page 33: Phpunit入门 r2

测试驱动开发 (TDD):例子

$phpunit MyTest.phpPHPUnit 3.2.18 by Sebastian Bergmann.

.

Time: 0 seconds

OK (1 test)

Page 34: Phpunit入门 r2

测试范围分析• 查看代码有哪些被测试了,有哪些没有被测试,用不同的颜色区分开

• 需要 xdebug扩展支持• 输出结果: html、 xml

– phpunit --coverage-html ./reports MyTest.php– phpunit --coverage-xml report.xml MyTest.php

• 覆盖级别:类、方法、行• 支持元标签:

@covers、@codeCoverageIgnoreStart和@codeCoverageIgnoreEnd

Page 35: Phpunit入门 r2

测试范围分析$phpunit –coverage-html ./reports MyTest.php

Page 36: Phpunit入门 r2

更多 ... ...• 官方网站:• http://www.phpunit.de/• http://planet.phpunit.de/

• 例子(谁在使用 PHPUnit):• http://www.phpunit.de/wiki/WhoUsesPHPUnit• (ZendFramework、 PHP-Gtk2、 Phing... ...)

• 相关工具:• http://www.phpundercontrol.org• http://cruisecontrol.sourceforge.net/• http://www.xdebug.org