在PHP中使用Mockery进行测试驱动开发(TDD)
测试驱动开发网上也谈了很多了,PHP方面的文章也有一些,在百度和Google里搜,好像没有看到几篇谈用Mock(伪装对象)的技术的,这里写篇文章讲讲。
先过一下测试驱动开发的基本理念:就是先写测试用例(一般这个测试用例都是自动化的单元测试用例,便于快速回滚执行),然后通过逐步修复测试用例的方法补齐产品代码,最后测试用例修复完毕后,产品也就写完了。
从我自己的实践中,我认为在类库开发的时候使用测试驱动开发技术是一个很好的方案,理由如下:
能够写出测试用例,即说明对问题域已经有一个清晰的了解,
节省了写文档的时间,测试用例就是类库调用的示例代码了。
代码质量有保证,因为写类库的过程就是修复测试用例的过程,所以测试用例修复完毕后类库也就写完了。
便于估时,估计类库开发时间的问题就简化成估计修复测试用例的时间了,相对于来说估时容易一些。
我们以编写一个字符串转数字的函数为例讲解测试驱动开发的理念,再引入Mock技术。在开始之前,需要安装PHPUnit和Mockery库(本文不使用PHPUnit自带的Mock库):
# 安装PHPUnitpear config-set auto_discover 1pear install pear.phpunit.de/PHPUnit# 安装Mock库sudo pear channel-discover pear.survivethedeepend.comsudo pear channel-discover hamcrest.googlecode.com/svn/pearsudo pear install --alldeps deepend/Mockery
那从测试驱动开发的理念来做的话,我们先写测试用例 ? parseinttest.php:
<? class ParseIntTest extends PHPUnit_Framework_TestCase { public function testParseIntBasic() { $v = parse_int("12345"); $this->assertEquals(12345, $v); $v = parse_int("-12345"); $this->assertEquals(-12345, $v); /* $v = parse_int("abcd"); $this->assertEquals(0, $v); $v = parse_int("0xab12"); $this->assertEquals(0xab12, $v); $v = parse_int("01b"); $this->assertEquals(1, $v); */ } }?>
上面的代码里,我们通过单元测试用例指定了要实现的函数parse_int的需求,即可以解析整数、带符号的整数等,又因为时间和资源的限制,那我们去掉了对十六进制和二进制的支持。
运行下面的命令执行测试用例:
phpunit --verbose parseinttest
因为这个时间没有任何代码,所以得到期望的错误 ? PHPUnit告诉我们找不到parse_int这个函数:
PHPUnit 3.6.12 by Sebastian Bergmann.
PHP Fatal error: Call to undefined function parse_int() in /var/www/pmdemo/parseinttest2.php on line 6
那我们先建一个空的parse_int函数 ? parseint.php:
<? function parse_int($str) { return 0; }?>
上面的代码里我们先不实现函数parse_int的任何逻辑,再运行测试用例,得到:
shiyimin@ubuntu :/var/www/pmdemo$ phpunit --verbose parseinttest
PHPUnit 3.6.12 by Sebastian Bergmann.
F
Time: 0 seconds, Memory: 2.75Mb
There was 1 failure:
1) ParseIntTest::testParseIntBasic
Failed asserting that 0 matches expected 12345.
/var/www/pmdemo/parseinttest.php:7
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
从上面红色高亮显示出来的错误消息,我们知道是测试用例里的第一个判断没有通过,即下面的判断语句没有执行成功:
$this->assertEquals(12345, $v);
这是因为我们的parse_int函数总是返回0这个值,发现了这个错误,我们来补齐这个逻辑以修复测试用例:
parseint.php
<? function parse_int($str) { $result = 0; $i = 0; for ( $i = 0; $i < strlen($str); ++$i ) { $result *= 10; $result += $str[$i] - '0'; } return $result; }?>
再次运行测试用例:
shiyimin@ubuntu :/var/www/pmdemo$ phpunit --verbose parseinttest
PHPUnit 3.6.12 by Sebastian Bergmann.
F
Time: 0 seconds, Memory: 2.75Mb
There was 1 failure:
1) ParseIntTest::testParseIntBasic
Failed asserting that 12345 matches expected -12345.
/var/www/pmdemo/parseinttest.php:10
FAILURES!
Tests: 1, Assertions: 2, Failures: 1.
从上面的结果可以看出,第一个测试用例已经修复了,现在是在处理带符号的字符串时,发生了问题,继续修复代码:
parseint.php
<? function parse_int($str) { $result = 0; $i = 0; $neg = 1; if ( $str[0] == '-' ) { $neg = -1; } for ( $i = 0; $i < strlen($str); ++$i ) { $result *= 10; $result += $str[$i] - '0'; } return $result * $neg; }?>
再运行测试用例:
shiyimin@ubuntu :/var/www/pmdemo$ phpunit --verbose parseinttest
PHPUnit 3.6.12 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 2.75Mb
OK (1 test, 2 assertions)
好了,这次所有测试用例都通过了,那我们的产品代码的实现也告一段落了,当然文章为了讲解方便,上面的代码并不是一个完整的实现,例如它就无法处理字符串“+12345”的情形。
下篇文章讲解如何在PHPUnit里应用Mock技术。

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Laravel simplifies handling temporary session data using its intuitive flash methods. This is perfect for displaying brief messages, alerts, or notifications within your application. Data persists only for the subsequent request by default: $request-

The PHP Client URL (cURL) extension is a powerful tool for developers, enabling seamless interaction with remote servers and REST APIs. By leveraging libcurl, a well-respected multi-protocol file transfer library, PHP cURL facilitates efficient execution of various network protocols, including HTTP, HTTPS, and FTP. This extension offers granular control over HTTP requests, supports multiple concurrent operations, and provides built-in security features.

Laravel provides concise HTTP response simulation syntax, simplifying HTTP interaction testing. This approach significantly reduces code redundancy while making your test simulation more intuitive. The basic implementation provides a variety of response type shortcuts: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

Do you want to provide real-time, instant solutions to your customers' most pressing problems? Live chat lets you have real-time conversations with customers and resolve their problems instantly. It allows you to provide faster service to your custom

Laravel's service container and service providers are fundamental to its architecture. This article explores service containers, details service provider creation, registration, and demonstrates practical usage with examples. We'll begin with an ove

PHP logging is essential for monitoring and debugging web applications, as well as capturing critical events, errors, and runtime behavior. It provides valuable insights into system performance, helps identify issues, and supports faster troubleshoot

Article discusses late static binding (LSB) in PHP, introduced in PHP 5.3, allowing runtime resolution of static method calls for more flexible inheritance.Main issue: LSB vs. traditional polymorphism; LSB's practical applications and potential perfo

The article discusses adding custom functionality to frameworks, focusing on understanding architecture, identifying extension points, and best practices for integration and debugging.
