SlideShare a Scribd company logo
PHPUnit 入门

                PHP User Group Shanghai 2008-04-26
                          Zhou Xianhua
                           BaohuaCai


PHP User Group Shanghai
                                1
2008
测试 ?
    • 测试方法
          – 黑盒测试
          – 白盒测试
    • 测试过程
          –   单元测试
          –   集成测试
          –   压力测试
          –   并发测试
          –   环境测试

PHP User Group Shanghai
                           2
2008
为 什么 要进 行单 元测试 ?
    •    保证代码按照特定的行为运行
    •    减少 Bug
    •    提高整体项目开发效率
    •    便于项目后续的维护




PHP User Group Shanghai
                          3
2008
常见 的测试 工具
    • PHP
          – PHPUnit 、 SimpleTest
    • ActionScript
          – AsUnit
    • Javascript
          – JsUnit 、 scriptaculous(unittest) 、 crosscheck
    • Java
          – Junit 、 TestNG
    • Python
          – PyUnit

PHP User Group Shanghai
                                 4
2008
PHPUnit 的特性
    • 安装、使用方便,是 xUnit 家族中的一员
    • 完全支持 PHP5
    • 开源、免费、有详细的文档供参考及官方支持
    • 提供多种格式的测试输出
      ( XML 、 JSON 、 TAP... )
    • 可以自动生成测试类( --skeleton )及从测试类
      生成应用类
    • 提供 Selenium RC 接口,便于在真实的浏览器中
      测试,实现基于 WEB 的功能测试。
    • 参考: http://www.phpunit.de/wiki/Features
PHP User Group Shanghai
                               5
2008
安装 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
                                 6
2008
安装成功
    运行 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
                                7
2008
传统 的测试
// 测试输入的用户名是否合法
function checkName($name)
{
    return (bool)preg_match('/^[w_d]{3,30}$/', $name);
}
// 传统的测试方法
echo checkName(”testUserName”) ? ”Y” : ”N”;
var_dump(checkName(” ”));
if(checkName(”......”)) echo ”...”;
第一个 PHPUnit 测试
// CheckNameTest.php
require_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”));
     }
}
运 行第一个 PHPUnit 测试
$phpunit CheckNameTest.php

PHPUnit 3.2.18 by Sebastian Bergmann.

Time: 0 seconds

OK (1 test)
测试步骤
1. 将类 Class 的测试写入 ClassTest
2. ClassTest 继承(通常)自
   PHPUnit_Framework_TestCase
3. 测试都是公用方法,命名为 test*
4. 在测试方法中,类似 assertEquals() 的断
   言方法用来断言一个实际值(应该)匹配
   一个期望值
数据提供者
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);    
    }
}
含有通过 和失败 的测试
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);
   }
}
含有通过 和失败 的测试结 果
.F
Time: 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
不同的测试结 果
.
    测试成功输出
F
    测试当中断言失败时输出
E
    测试有错误发生时输出
S
    测试被跳过时输出
I
    测试未完成时输出
有错误发 生的测试 ( E )
public function testError() {
   $this->assertLessThan(3);
   $this->assertEquals(”E?”);
}
---------
E
1) testFailure(MyTest)
Missing argument 2 for
   PHPUnit_Framework_Assert::assertLessThan(),
   called in ... ...
被跳过 的测试 ( S )
public function testSkip() {
    $this->markTestSkipped("Skipped test!");
    // stop!!!
    $this->assertTrue(true);
}
---
$phpunit –verbose MyTest.php
S
...
1) testSkip(MyTest)
Skipped test!
...
未完成的测试 ( I )
public function testIncomplete() {
    $this->markTestIncomplete("Incomplete test!");
    // stop!!!
    $this->assertTrue(true);
}
---
$phpunit –verbose MyTest.php
I
...
1) testIncomplete(MyTest)
Incomplete test!
...
夹 具 (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);
    }
}
夹 具 (Fixtures)

    setUp()
     testOne()
    tearDown()




     setUp()
    testTwo()
   tearDown()
同时测试 多个文件
// AllTests.php
require_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
...
同时测试 多个文件
// AllTests.php
require_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);
输 出测试
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";
   }
}
输 出测试 结 果
.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.
性能测试
require_once 'PHPUnit/Extensions/PerformanceTestCase.php';

class PerformanceTest
extends PHPUnit_Extensions_PerformanceTestCase
{
   public function testPerformance()
   {
     $this->setMaxRunningTime(2);
     sleep(1);
   }
}
其它扩 展测试
• 数据库测试
  – PHPUnit_Extensions_Database_TestCase
• PHP 格式测试
  – PHPUnit_Extensions_PhptTestCase
  – http://qa.php.net/write-test.php
• Selenium Rc 测试
  – PHPUnit_Extensions_SeleniumTestCase
  – http://selenium.openqa.org/
测试驱动开发 (TDD)
• 主要开发步骤
  – 1. 编写测试用例
  – 2. 运行测试用例(此时测试结果必然是失败的)
  – 3. 为测试用例编写代码
  – 4. 再次运行测试用例(测试结果是成功或失败的)
    若失败则返回第 3 步继续。
  – 5. 根据需要清除 / 优化相关代码(重构),收工 !


  Test     Code   Test    Code
测试驱动开发 (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;
   }
}
测试驱动开发 (TDD) :例子
$phpunit MyTest.php

Fatal error: require_once(): Failed opening
   required 'Cal.php' (include_path='.:
... ...
测试驱动开发 (TDD) :例子
class Cal {
   public function add() {
   }
}
测试驱动开发 (TDD) :例子
phpunit MyTest.php

F

Time: 0 seconds

There was 1 failure:

1) testAdd(MyTest)
Failed asserting that <null> matches expected value <integer:3>.
测试驱动开发 (TDD) :例子
class Cal {
   public function add($a, $b) {
     return $a + $b;
   }
}
测试驱动开发 (TDD) :例子
$phpunit MyTest.php
PHPUnit 3.2.18 by Sebastian Bergmann.

.

Time: 0 seconds


OK (1 test)
测试 范围 分析
• 查看代码有哪些被测试了,有哪些没有被测试,
  用不同的颜色区分开
• 需要 xdebug 扩展支持
• 输出结果: html 、 xml
  – phpunit --coverage-html ./reports MyTest.php
  – phpunit --coverage-xml report.xml MyTest.php
• 覆盖级别:类、方法、行
• 支持元标签:
  @covers 、 @codeCoverageIgnoreStart 和
  @codeCoverageIgnoreEnd
测试 范围 分析
$phpunit –coverage-html ./reports MyTest.php
更多 ... ...
• 官方网站:
• 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

More Related Content

What's hot

PHPUnit slide formal
PHPUnit slide formalPHPUnit slide formal
PHPUnit slide formaljameslabs
 
PHPUnit
PHPUnitPHPUnit
PHPUnit
jameslabs
 
Testing in python 2.7.3
Testing in python 2.7.3Testing in python 2.7.3
Testing in python 2.7.3Wen Liao
 
Php Extension--yahoo(Cc0cc)
Php Extension--yahoo(Cc0cc)Php Extension--yahoo(Cc0cc)
Php Extension--yahoo(Cc0cc)
sunlick
 
J2ee面试知识
J2ee面试知识J2ee面试知识
J2ee面试知识yiditushe
 
PHPUnit + Xdebug 单元测试技术
PHPUnit + Xdebug 单元测试技术PHPUnit + Xdebug 单元测试技术
PHPUnit + Xdebug 单元测试技术
hoopchina
 
Free rtos workshop1@nuu
Free rtos workshop1@nuuFree rtos workshop1@nuu
Free rtos workshop1@nuu
紀榮 陳
 
Net Parallel Programming .NET平行處理與執行序
Net Parallel Programming .NET平行處理與執行序Net Parallel Programming .NET平行處理與執行序
Net Parallel Programming .NET平行處理與執行序HO-HSUN LIN
 
軟體工程(總結篇)
軟體工程(總結篇)軟體工程(總結篇)
軟體工程(總結篇)
鍾誠 陳鍾誠
 
OpenEJB - 另一個選擇
OpenEJB - 另一個選擇OpenEJB - 另一個選擇
OpenEJB - 另一個選擇
Justin Lin
 
由一个简单的程序谈起--之四
由一个简单的程序谈起--之四由一个简单的程序谈起--之四
由一个简单的程序谈起--之四yiditushe
 
线程与并发
线程与并发线程与并发
线程与并发Tony Deng
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
keelii
 
The ruby way test
The ruby way testThe ruby way test
The ruby way testDeng Peng
 
深入淺出 Web 容器 - Tomcat 原始碼分析
深入淺出 Web 容器  - Tomcat 原始碼分析深入淺出 Web 容器  - Tomcat 原始碼分析
深入淺出 Web 容器 - Tomcat 原始碼分析
Justin Lin
 
Puppet安装总结
Puppet安装总结Puppet安装总结
Puppet安装总结Yiwei Ma
 
Inside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutor
Inside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutorInside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutor
Inside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutorAdy Liu
 
Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)FLASH开发者交流会
 
Memcached内存分析、调优、集群
Memcached内存分析、调优、集群Memcached内存分析、调优、集群
Memcached内存分析、调优、集群
hik_lhz
 
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Hazem Saleh
 

What's hot (20)

PHPUnit slide formal
PHPUnit slide formalPHPUnit slide formal
PHPUnit slide formal
 
PHPUnit
PHPUnitPHPUnit
PHPUnit
 
Testing in python 2.7.3
Testing in python 2.7.3Testing in python 2.7.3
Testing in python 2.7.3
 
Php Extension--yahoo(Cc0cc)
Php Extension--yahoo(Cc0cc)Php Extension--yahoo(Cc0cc)
Php Extension--yahoo(Cc0cc)
 
J2ee面试知识
J2ee面试知识J2ee面试知识
J2ee面试知识
 
PHPUnit + Xdebug 单元测试技术
PHPUnit + Xdebug 单元测试技术PHPUnit + Xdebug 单元测试技术
PHPUnit + Xdebug 单元测试技术
 
Free rtos workshop1@nuu
Free rtos workshop1@nuuFree rtos workshop1@nuu
Free rtos workshop1@nuu
 
Net Parallel Programming .NET平行處理與執行序
Net Parallel Programming .NET平行處理與執行序Net Parallel Programming .NET平行處理與執行序
Net Parallel Programming .NET平行處理與執行序
 
軟體工程(總結篇)
軟體工程(總結篇)軟體工程(總結篇)
軟體工程(總結篇)
 
OpenEJB - 另一個選擇
OpenEJB - 另一個選擇OpenEJB - 另一個選擇
OpenEJB - 另一個選擇
 
由一个简单的程序谈起--之四
由一个简单的程序谈起--之四由一个简单的程序谈起--之四
由一个简单的程序谈起--之四
 
线程与并发
线程与并发线程与并发
线程与并发
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
 
The ruby way test
The ruby way testThe ruby way test
The ruby way test
 
深入淺出 Web 容器 - Tomcat 原始碼分析
深入淺出 Web 容器  - Tomcat 原始碼分析深入淺出 Web 容器  - Tomcat 原始碼分析
深入淺出 Web 容器 - Tomcat 原始碼分析
 
Puppet安装总结
Puppet安装总结Puppet安装总结
Puppet安装总结
 
Inside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutor
Inside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutorInside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutor
Inside.java.concurrency 35.thread pool.part8_future.scheduledthreadpoolexecutor
 
Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)
 
Memcached内存分析、调优、集群
Memcached内存分析、调优、集群Memcached内存分析、调优、集群
Memcached内存分析、调优、集群
 
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
 

Viewers also liked

Soinujolearen semea
Soinujolearen semeaSoinujolearen semea
Soinujolearen semeamikeldean
 
Anne meininger usa
Anne meininger usaAnne meininger usa
Anne meininger usaguest0683c19
 
ordenagailuko osagaiak
ordenagailuko osagaiakordenagailuko osagaiak
ordenagailuko osagaiakmikeldean
 
Hybrid library
Hybrid libraryHybrid library
Hybrid library
MaryH54
 
Ppt0000001
Ppt0000001Ppt0000001
Ppt0000001
Ángeles Cuéllar
 

Viewers also liked (8)

Pianoa
PianoaPianoa
Pianoa
 
Soinujolearen semea
Soinujolearen semeaSoinujolearen semea
Soinujolearen semea
 
Aurkakoak
AurkakoakAurkakoak
Aurkakoak
 
Inauteriak
InauteriakInauteriak
Inauteriak
 
Anne meininger usa
Anne meininger usaAnne meininger usa
Anne meininger usa
 
ordenagailuko osagaiak
ordenagailuko osagaiakordenagailuko osagaiak
ordenagailuko osagaiak
 
Hybrid library
Hybrid libraryHybrid library
Hybrid library
 
Ppt0000001
Ppt0000001Ppt0000001
Ppt0000001
 

Similar to Phpunit入门 r2

使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)
Max Lai
 
Foundation of software development 1
Foundation of software development 1Foundation of software development 1
Foundation of software development 1netdbncku
 
广告技术部自动化测试介绍.pdf
广告技术部自动化测试介绍.pdf广告技术部自动化测试介绍.pdf
广告技术部自动化测试介绍.pdfbj_qa
 
Java script测试之js unit ut
Java script测试之js unit utJava script测试之js unit ut
Java script测试之js unit utfangdeng
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践yiditushe
 
Java单元测试
Java单元测试Java单元测试
Java单元测试darlingshan
 
PHP 单元测试
PHP 单元测试PHP 单元测试
PHP 单元测试
Lan Yanguang
 
02.python.开发最佳实践
02.python.开发最佳实践02.python.开发最佳实践
02.python.开发最佳实践Na Lee
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
javatwo2011
 
Maven初级培训
Maven初级培训Maven初级培训
Maven初级培训ytsolar
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops
琛琳 饶
 
JavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization SkillsJavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization Skills
Ho Kim
 
Junit使用指南及作业规范
Junit使用指南及作业规范Junit使用指南及作业规范
Junit使用指南及作业规范
dong jiang
 
C语言benchmark覆盖信息收集总结4
C语言benchmark覆盖信息收集总结4C语言benchmark覆盖信息收集总结4
C语言benchmark覆盖信息收集总结4Tao He
 
Javascript autoload
Javascript autoloadJavascript autoload
Javascript autoloadjay li
 
钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会Zhi Zhong
 
部分PHP问题总结[转贴]
部分PHP问题总结[转贴]部分PHP问题总结[转贴]
部分PHP问题总结[转贴]wensheng wei
 

Similar to Phpunit入门 r2 (20)

使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)
 
Foundation of software development 1
Foundation of software development 1Foundation of software development 1
Foundation of software development 1
 
广告技术部自动化测试介绍.pdf
广告技术部自动化测试介绍.pdf广告技术部自动化测试介绍.pdf
广告技术部自动化测试介绍.pdf
 
Java script测试之js unit ut
Java script测试之js unit utJava script测试之js unit ut
Java script测试之js unit ut
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
 
Java单元测试
Java单元测试Java单元测试
Java单元测试
 
PHP 单元测试
PHP 单元测试PHP 单元测试
PHP 单元测试
 
02.python.开发最佳实践
02.python.开发最佳实践02.python.开发最佳实践
02.python.开发最佳实践
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
 
Maven初级培训
Maven初级培训Maven初级培训
Maven初级培训
 
运维自动化
运维自动化运维自动化
运维自动化
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops
 
JavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization SkillsJavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization Skills
 
Junit使用指南及作业规范
Junit使用指南及作业规范Junit使用指南及作业规范
Junit使用指南及作业规范
 
Asp net
Asp net Asp net
Asp net
 
C语言benchmark覆盖信息收集总结4
C语言benchmark覆盖信息收集总结4C语言benchmark覆盖信息收集总结4
C语言benchmark覆盖信息收集总结4
 
Javascript autoload
Javascript autoloadJavascript autoload
Javascript autoload
 
钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会
 
部分PHP问题总结[转贴]
部分PHP问题总结[转贴]部分PHP问题总结[转贴]
部分PHP问题总结[转贴]
 
Sun java
Sun javaSun java
Sun java
 

Phpunit入门 r2

  • 1. PHPUnit 入门 PHP User Group Shanghai 2008-04-26 Zhou Xianhua BaohuaCai PHP User Group Shanghai 1 2008
  • 2. 测试 ? • 测试方法 – 黑盒测试 – 白盒测试 • 测试过程 – 单元测试 – 集成测试 – 压力测试 – 并发测试 – 环境测试 PHP User Group Shanghai 2 2008
  • 3. 为 什么 要进 行单 元测试 ? • 保证代码按照特定的行为运行 • 减少 Bug • 提高整体项目开发效率 • 便于项目后续的维护 PHP User Group Shanghai 3 2008
  • 4. 常见 的测试 工具 • PHP – PHPUnit 、 SimpleTest • ActionScript – AsUnit • Javascript – JsUnit 、 scriptaculous(unittest) 、 crosscheck • Java – Junit 、 TestNG • Python – PyUnit PHP User Group Shanghai 4 2008
  • 5. PHPUnit 的特性 • 安装、使用方便,是 xUnit 家族中的一员 • 完全支持 PHP5 • 开源、免费、有详细的文档供参考及官方支持 • 提供多种格式的测试输出 ( XML 、 JSON 、 TAP... ) • 可以自动生成测试类( --skeleton )及从测试类 生成应用类 • 提供 Selenium RC 接口,便于在真实的浏览器中 测试,实现基于 WEB 的功能测试。 • 参考: http://www.phpunit.de/wiki/Features PHP User Group Shanghai 5 2008
  • 6. 安装 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 6 2008
  • 7. 安装成功 运行 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 7 2008
  • 8. 传统 的测试 // 测试输入的用户名是否合法 function checkName($name) { return (bool)preg_match('/^[w_d]{3,30}$/', $name); } // 传统的测试方法 echo checkName(”testUserName”) ? ”Y” : ”N”; var_dump(checkName(” ”)); if(checkName(”......”)) echo ”...”;
  • 9. 第一个 PHPUnit 测试 // CheckNameTest.php require_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”)); } }
  • 10. 运 行第一个 PHPUnit 测试 $phpunit CheckNameTest.php PHPUnit 3.2.18 by Sebastian Bergmann. Time: 0 seconds OK (1 test)
  • 11. 测试步骤 1. 将类 Class 的测试写入 ClassTest 2. ClassTest 继承(通常)自 PHPUnit_Framework_TestCase 3. 测试都是公用方法,命名为 test* 4. 在测试方法中,类似 assertEquals() 的断 言方法用来断言一个实际值(应该)匹配 一个期望值
  • 12. 数据提供者 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);     } }
  • 13. 含有通过 和失败 的测试 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); } }
  • 14. 含有通过 和失败 的测试结 果 .F Time: 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
  • 15. 不同的测试结 果 . 测试成功输出 F 测试当中断言失败时输出 E 测试有错误发生时输出 S 测试被跳过时输出 I 测试未完成时输出
  • 16. 有错误发 生的测试 ( E ) public function testError() { $this->assertLessThan(3); $this->assertEquals(”E?”); } --------- E 1) testFailure(MyTest) Missing argument 2 for PHPUnit_Framework_Assert::assertLessThan(), called in ... ...
  • 17. 被跳过 的测试 ( S ) public function testSkip() { $this->markTestSkipped("Skipped test!"); // stop!!! $this->assertTrue(true); } --- $phpunit –verbose MyTest.php S ... 1) testSkip(MyTest) Skipped test! ...
  • 18. 未完成的测试 ( I ) public function testIncomplete() { $this->markTestIncomplete("Incomplete test!"); // stop!!! $this->assertTrue(true); } --- $phpunit –verbose MyTest.php I ... 1) testIncomplete(MyTest) Incomplete test! ...
  • 19. 夹 具 (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); } }
  • 20. 夹 具 (Fixtures) setUp() testOne() tearDown() setUp() testTwo() tearDown()
  • 21. 同时测试 多个文件 // AllTests.php require_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 ...
  • 22. 同时测试 多个文件 // AllTests.php require_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);
  • 23. 输 出测试 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"; } }
  • 24. 输 出测试 结 果 .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.
  • 25. 性能测试 require_once 'PHPUnit/Extensions/PerformanceTestCase.php'; class PerformanceTest extends PHPUnit_Extensions_PerformanceTestCase { public function testPerformance() { $this->setMaxRunningTime(2); sleep(1); } }
  • 26. 其它扩 展测试 • 数据库测试 – PHPUnit_Extensions_Database_TestCase • PHP 格式测试 – PHPUnit_Extensions_PhptTestCase – http://qa.php.net/write-test.php • Selenium Rc 测试 – PHPUnit_Extensions_SeleniumTestCase – http://selenium.openqa.org/
  • 27. 测试驱动开发 (TDD) • 主要开发步骤 – 1. 编写测试用例 – 2. 运行测试用例(此时测试结果必然是失败的) – 3. 为测试用例编写代码 – 4. 再次运行测试用例(测试结果是成功或失败的) 若失败则返回第 3 步继续。 – 5. 根据需要清除 / 优化相关代码(重构),收工 ! Test Code Test Code
  • 28. 测试驱动开发 (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; } }
  • 29. 测试驱动开发 (TDD) :例子 $phpunit MyTest.php Fatal error: require_once(): Failed opening required 'Cal.php' (include_path='.: ... ...
  • 30. 测试驱动开发 (TDD) :例子 class Cal { public function add() { } }
  • 31. 测试驱动开发 (TDD) :例子 phpunit MyTest.php F Time: 0 seconds There was 1 failure: 1) testAdd(MyTest) Failed asserting that <null> matches expected value <integer:3>.
  • 32. 测试驱动开发 (TDD) :例子 class Cal { public function add($a, $b) { return $a + $b; } }
  • 33. 测试驱动开发 (TDD) :例子 $phpunit MyTest.php PHPUnit 3.2.18 by Sebastian Bergmann. . Time: 0 seconds OK (1 test)
  • 34. 测试 范围 分析 • 查看代码有哪些被测试了,有哪些没有被测试, 用不同的颜色区分开 • 需要 xdebug 扩展支持 • 输出结果: html 、 xml – phpunit --coverage-html ./reports MyTest.php – phpunit --coverage-xml report.xml MyTest.php • 覆盖级别:类、方法、行 • 支持元标签: @covers 、 @codeCoverageIgnoreStart 和 @codeCoverageIgnoreEnd
  • 35. 测试 范围 分析 $phpunit –coverage-html ./reports MyTest.php
  • 36. 更多 ... ... • 官方网站: • 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