无返回值的方法,可以通过其他方法读取属性,也可以使用对象类型中的断言来判断属性的改变。
PHP代码
- /**
- * Unit类,有一个无返回值方法
- */
- class Unit
- {
- protected $name;
- /**
- * 设置name属性
- */
- public function setName($value)
- {
- $this->name = $value;
- }
- }
- ?>
PHP代码
编写测试
编写测试的原则是,尽可能测试每种不同的参数调用和不同的返回结果类型,既要测试成功的情况,也要测试失败的情况;无返回值的情况,要测试属性改变、输出内容、异常类型等;测试后记得要恢复现场。
在这里做了超出自己能力的事并不光荣。在你写某个函数之前,你只想让它做加法,但它却能做乘法,而且单元测试正确通过。我们来看看它是怎么做到的。
PHP代码
- /**
- * 计算器类
- */
- class Calculator
- {
- /**
- * 做加法运算
- *
- * @param int $a
- * @param int $b
- * @return int
- */
- public function add($a, $b)
- {
- return $a * $b;
- }
- }
- ?>
PHP代码
- require_once 'Calculator.php';
- class CalcuatorTest extends PHPUnit_Framework_TestCase
- {
- public function testadd()
- {
- // 创建实例
- $c = new Calculator();
- $expected = 4;
- // 做加法
- $result = $c->add(2, 2);
- $this->assertEquals($expected, $result);
- }
- }
- ?>
合理的测试能帮助我们尽早发现错误。add()方法有两个参数,测试的时候用了两个值相同的参数。如果多做几次测试又太麻烦,对于这个测试我们按照科学的方法只需要一次。从概率学上讲,当你使用的参数差异越大时,结果相同的概率越低。
对于只有几个返回值的情况,要测试全部,如布尔类型。
PHP代码
- /**
- * File.php
- */
- /**
- * 在文件中写入数据并保存
- *
- * @param string $path
- * @param string $data
- * @return bool
- */
- function Save($path, $data)
- {
- if (is_dir($path)) {
- return FALSE;
- }
- return file_put_contents($path, $data);
- }
- ?>
PHP代码
- /**
- * FileTest.php
- */
- require_once 'File.php';
- class FileTest extends PHPUnit_Framework_TestCase
- {
- /**
- * 测试保存文件
- */
- public function testSave()
- {
- $file = 'IamFile.txt';
- $dir = 'IamDir';
- mkdir($dir);
- // 测试返回值为真的情况
- $this->assertTrue(Save($file, 'TestTrue'));
- // 测试返回值为假的情况
- $this->assertFalse(Save($dir, 'TestFalse'));
- // 恢复现场
- if (is_file($file)) {
- unlink($file);
- }
- rmdir($dir);
- }
- }
- ?>
对于有多种类型返回值或不同参数的情况,分别测试每种类型和参数。下面是ThinkPHP源代码中的一个函数,有点复杂。这个例子不能单独运行,如需要请用SVN导出最新的ThinkPHP源代码(含单元测试)。
PHP代码
- /**
- * URL生成函数
- *
- * @param string $action 方法名
- * @param string $module 模块名
- * @param string $route 路由名
- * @param array $params 参数
- */
- function url($action=ACTION_NAME,$module=MODULE_NAME,$route='',$app=APP_NAME,$params=array())
- {
- if(C('DISPATCH_ON') && C('URL_MODEL')>0) {
- switch(C('PATH_MODEL')) {
- case 1:// 普通PATHINFO模式
- $str = '/';
- foreach ($params as $var=>$val)
- $str .= $var.'/'.$val.'/';
- $str = substr($str,0,-1);
- if(!emptyempty($route)) {
- $url = str_replace(APP_NAME,$app,).'/'.C('VAR_ROUTER').'/'.$route.'/'.$str;
- }else{
- $url = str_replace(APP_NAME,$app,).'/'.C('VAR_MODULE').'/'.$module.'/'.C('VAR_ACTION').'/'.$action.$str;
- }
- break;
- case 2:// 智能PATHINFO模式
- $depr = C('PATH_DEPR');
- $str = $depr;
- foreach ($params as $var=>$val)
- $str .= $var.$depr.$val.$depr;
- $str = substr($str,0,-1);
- if(!emptyempty($route)) {
- $url = str_replace(APP_NAME,$app,).'/'.$route.$str;
- }else{
- $url = str_replace(APP_NAME,$app,).'/'.$module.$depr.$action.$str;
- }
- break;
- }
- if(C('HTML_URL_SUFFIX')) {
- $url .= C('HTML_URL_SUFFIX');
- }
- }else{
- $params = http_build_query($params);
- if(!emptyempty($route)) {
- $url = str_replace(APP_NAME,$app,).'?'.C('VAR_ROUTER').'='.$route.'&'.$params;
- }else{
- $url = str_replace(APP_NAME,$app,).'?'.C('VAR_MODULE').'='.$module.'&'.C('VAR_ACTION').'='.$action.'&'.$params;
- }
- }
- return $url;
- }
- ?>