phpunit + xdebug 单元测试技术

51

Click here to load reader

Upload: hoopchina

Post on 17-May-2015

3.909 views

Category:

Education


8 download

DESCRIPTION

PHPUnit + Xdebug 单元测试技术推广 Keynote。

TRANSCRIPT

Page 1: PHPUnit + Xdebug 单元测试技术

PHPUnit + Xdebug 单元测试技术

—— 提升编码质量的工具和方法

Page 2: PHPUnit + Xdebug 单元测试技术

讨论的主题• PHPUnit 单元测试技术• Xdebug 调试

Page 3: PHPUnit + Xdebug 单元测试技术

声明• 这仅是一个宣传、引导• 会写测试并提升了 工作质量、减少返工次

数 的程序员,牧师 老大说了,会更容易得到管理层的奖励和青睐

Page 4: PHPUnit + Xdebug 单元测试技术

如何测试…测试基础

Page 5: PHPUnit + Xdebug 单元测试技术

一个例子 : Stack.php<?phpclass Stack{ private $store;

public function __construct() { $this->store = array(); }

public function push($o) { array_push($this->store, $o); }

public function pop() { return array_pop($this->store); }

public function count() { return count($this->store); }}

Page 6: PHPUnit + Xdebug 单元测试技术

如何保证正确性 ?

• 手眼测试…– 在程序底部添加一些测试语句

$stack = new Stack;

if ($stack) { echo $stack->count(); $stack->push(1111); echo $stack->count(); echo $stack->pop(); echo $stack->count();}

Page 7: PHPUnit + Xdebug 单元测试技术

测试成功后…• 剔除 / 注释 掉这些语句…

Page 8: PHPUnit + Xdebug 单元测试技术

下一次再修改时…• 重新加上这些测试语句 , 并再次测试

– 回归测试

Page 9: PHPUnit + Xdebug 单元测试技术

问题是…• 每次修改都要重新加上这些测试 , 以验证

没有 ( 未预期地 ) 破坏原有功能…– 好吧 , 为何不把测试独立出来呢 ?

Page 10: PHPUnit + Xdebug 单元测试技术

好主意 !!

• 把测试独立成一个文件 , 每次执行一下即可– 无需再做 剔除 / 注释 – 加上 / 反注释 工作了StackTest.php

-------------------------------------------------------------------------------------------<?phprequire_once ‘./Stack.php’;

$stack = new Stack;if ($stack) { echo $stack->count(); $stack->push(1111); echo $stack->count(); echo $stack->pop(); echo $stack->count();}

Page 11: PHPUnit + Xdebug 单元测试技术

新问题是…• 每次都要 手眼测试 , 太累了 !!!

– 呣 , 有没有办法让 机器 去做 ?– 然后自己就有时间去 把妹子…

Page 12: PHPUnit + Xdebug 单元测试技术

PHPUnit 来帮忙<?php

require_once './Stack.php';

class StackTest extends PHPUnit_Framework_TestCase

{

public function testCanPushAndPop() {

$stack = new Stack();

$this->assertEquals(0, $stack->count());

$stack->push('foo');

$this->assertEquals(1, $stack->count());

$this->assertEquals('foo', $stack->pop());

$this->assertEquals(0, $stack->count());

}

}

Page 13: PHPUnit + Xdebug 单元测试技术

执行测试$ phpunit StackTest

Page 14: PHPUnit + Xdebug 单元测试技术

执行测试成功时 :

Page 15: PHPUnit + Xdebug 单元测试技术

执行测试失败时 :

Page 16: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 17: PHPUnit + Xdebug 单元测试技术

Stack 增加新功能时…<?phpclass Stack{ private $store;

public function __construct() { $this->store = array(); }

public function push($o) { array_push($this->store, $o); }

public function pop() { return array_pop($this->store); }

public function count() { return count($this->store); }

public function clean() { $this->store = array(); }}

Page 18: PHPUnit + Xdebug 单元测试技术

<?php

require_once './Stack.php';

class StackTest extends PHPUnit_Framework_TestCase

{

public function testCanPushAndPop() {

$stack = new Stack();

$this->assertEquals(0, $stack->count());

$stack->push('foo');

$this->assertEquals(1, $stack->count());

$this->assertEquals('foo', $stack->pop());

$this->assertEquals(0, $stack->count());

}

public function testCanClean() {

$stack = new Stack();

$stack->push('foo');

$this->assertEquals(1, $stack->count());

$stack->clean();

$this->assertEquals(0, $stack->count());

}

}

也要增加新测试…

Page 19: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 20: PHPUnit + Xdebug 单元测试技术

xUnit 方法的优势• 减少验证 ‘代码正确性’ 的工作量

– 自动化回归测试– 避免系统退步

• 写测试用例可以促使程序员发现边界条件• 测试用例本身就是很好的示范代码和文档• 写测试用例可以促使程序员真正了解需求• 完备的测试可以给程序员以信心• More…

Page 21: PHPUnit + Xdebug 单元测试技术

什么是测试 ?

• 测试是一组输入、执行条件以及预期结果的集合– 一组断言

• 测试是一个产品的详细接口规格– 如何调用,结果值会是如何, etc.

• 测试定义产品的每一个面• 测试是…

这一页 PPT 本身就是个测试…

Page 22: PHPUnit + Xdebug 单元测试技术

鸭子• “When I see a bird that walks like a duck and

swims like a duck and quacks like a duck, I call that bird a duck.”

– James Whitcomb Riley (1849 – 1916)

• (Duck typing)

Page 23: PHPUnit + Xdebug 单元测试技术

人• “ 人就是以为自己不是机器的机器”

– Wang Wenlin (1981 – ∞)

以为自己不是机器的机器 , 是人…

Page 24: PHPUnit + Xdebug 单元测试技术

框架中的测试Zend Framework & Symfony 1

Page 25: PHPUnit + Xdebug 单元测试技术

良好的测试支持• Zend Framework 集成 PHPUnit 支持• Symfony 1 使用自己的 Lime 测试框架

– Symfony 2 已改用 PHPUnit …

它们都能自动生成 功能测试 骨架…

Page 26: PHPUnit + Xdebug 单元测试技术

Zend Framework 示例$ zf create project demo

$ zf create controller foo

$ phpunit

Page 27: PHPUnit + Xdebug 单元测试技术

Zend Framework 示例<?php

class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase

{

public function testIndexAction()

{

$params = array('action' => 'index', 'controller' => 'Index', 'module' => 'default');

$urlParams = $this->urlizeOptions($params);

$url = $this->url($urlParams);

$this->dispatch($url);

// assertions

$this->assertModule($urlParams['module']);

$this->assertController($urlParams['controller']);

$this->assertAction($urlParams['action']);

$this->assertQueryContentContains("div#welcome h3", "This is your project's main page");

}

}

Page 28: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 29: PHPUnit + Xdebug 单元测试技术

Symfony 示例$ symfony generate:project demo

$ symfony generate:app foo

$ symfony generate:module foo bar

$ symfony test:all

$ symfony test:functional foo

Page 30: PHPUnit + Xdebug 单元测试技术

Symfony 示例<?php

include(dirname(__FILE__).'/../../bootstrap/functional.php');

$browser = new sfTestFunctional(new sfBrowser());

$browser->

get('/content/index')->

with('request')->begin()->

isParameter('module', 'content')->

isParameter('action', 'index')->

end()->

with('response')->begin()->

isStatusCode(200)->

checkElement('body', '!/This is a temporary page/')->

end()

;

Page 31: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 32: PHPUnit + Xdebug 单元测试技术

好消息…• 功能测试脚本 , 测试组会帮忙制作…• 程序员只需做单元测试

Page 33: PHPUnit + Xdebug 单元测试技术

PHPUNIT 还能做什么…

Page 34: PHPUnit + Xdebug 单元测试技术

代码覆盖报告$ phpunit --coverage-html cov StackTest

代码覆盖报告,一种调试工具。

Page 35: PHPUnit + Xdebug 单元测试技术
Page 36: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 37: PHPUnit + Xdebug 单元测试技术

生成规格文档$ phpunit --testdox StackTest

测试 即是 定义。

Page 38: PHPUnit + Xdebug 单元测试技术

生成规格文档

Page 39: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 40: PHPUnit + Xdebug 单元测试技术

测试失败时…Xdebug 来帮忙

Page 41: PHPUnit + Xdebug 单元测试技术

Xdebug 出场…• 简便的 PHP 调试、跟踪 和 剖析 工具

–我们主要用它的 远程调试功能

Page 42: PHPUnit + Xdebug 单元测试技术

如何调试一个测试 ?$ export XDEBUG_CONFIG="remote_host=192.168.8.91 idekey=netbeans-xdebug"

## plain old php

$ phpunit StackTest

## zend framework

$ phpunit application/controllers/FooControllerTest

## symfony 1

$ symfony test:functional foo

Page 43: PHPUnit + Xdebug 单元测试技术

断点

单步

上下文

Page 44: PHPUnit + Xdebug 单元测试技术

- 互动演示 -

Page 45: PHPUnit + Xdebug 单元测试技术

Xdebug 的其它能力…• 跟踪 (Trace)• 性能剖析 (Profile)

Page 46: PHPUnit + Xdebug 单元测试技术
Page 47: PHPUnit + Xdebug 单元测试技术

一点疑惑

Page 48: PHPUnit + Xdebug 单元测试技术

断言… 可以吗 ?

• 这种定义事物的方式可能并不充分–但至少是必要的

• 可是仍然是不够充分…–世界上从来没有 ‘完全充分’,就像合同不够充分,法律不会完美一样

–我们的目标是测试案例能覆盖到所有的代码路径即可

Page 49: PHPUnit + Xdebug 单元测试技术

测试不是测试组的事吗 ?

• 单元测试 习惯上、实践上 是 程序员写的– 只有程序员自己知道怎么测…–而且,它也是一种调试工具

• 功能测试 习惯上 是 测试组 来做–但仍然需要程序员的紧密配合

Page 50: PHPUnit + Xdebug 单元测试技术

最后…

Page 51: PHPUnit + Xdebug 单元测试技术

…谢谢 !!