测试也要设计—phpunit实践

简介:

概述
本文阐述如何利用面向对象的思想,在phpunit框架下实现测试用例、数据文件、配置信息和lib库等信息分离,并能有效组合。
也许有些QA认为,测试代码只要能满足测试要求即可,根本不需要有什么设计的理念。其实不然,好的测试代码,应该是可读性强,可扩展性强。以下分享一个我在实际项目中的小想法来阐述这个观点,仅作抛砖引玉之用。
具体实现
在autoFunc测试目录下,创建conf、data、lib三个目录,分别用于保存配置信息、数据文件和lib库,测试用例直接放在autoFunc下。
 


A 方案
直接在test_object_put_get.php中require config.php和util.php,如下:
require_once 'conf/config.php';
require_once 'lib/util.php';
似乎很简单,但这里却有两个问题,phpunit的测试用例,是以class继承PHPUnit_Framework_Testcase类的方式来组织的,这样在testcase中就无法访问config.php的变量列表,或许你会说,这个很好解决呀,直接的testcase的class中指定config.php的变量名为global类型即可,如下:
 



弊端1:config.php中有几个配置,testcase中就需要global几个,不免太手工了。
弊端2:util.php中function无法通过global方式声明,在testcase中也就无法访问到。
B 方案
鉴于A 方案的局限性,我提出了面向对象的方式,来实现配置信息、测试用例、lib库有效的隔离。B 方案最突出的地方在于引入了继承的概念,容我一一道来。
config.php
测试用例中总有一些常量会被反复使用到,使用配置文件的方式是所有测试人员的共识,在这里,我做了一个小小改善,将config信息包装为类的方式,以便于在lib库的类中使用到,如下:
class Config{
public $WEB_SITE = "http://test.com:8090/";
public $BUCKET = "vincent";
public $ACCESS_KEY = "jhPLaYVh11wo";
public $SECURE_KEY = "A23mtEjHwv1z";
public $SIGN_FLAG="TST";
public $DATA_DIR = "./data/";

//no use now
public $IP = "";
public $TIME = "";
}
util.php
编写测试用例时,总会有一些逻辑处理片段反复的出现,这造成了测试代码的大量冗余,也加大了维护成功,将这些逻辑处理封装为一个个函数是第一个步,之后将通用的函数抽取为lib库的形式,而那些函数适合抽取为lib库。根据经验我列举几个lib的共有特性:
1.与测试用例逻辑无关
2.完成单一职责
3.可被其他用例共用
如果满足这三个条件,那这个函数就可以抽取为lib库,如下文的signature签名函数。
在实际项目中,我抽取了部分函数为lib库,并将lib库也封装为类的形式,同时继承于class Config,如下:
require_once 'conf/config.php';
class Util extends Config{
/**
* 返回签名串
* @param string $method
* @param string $object
*/
public function signature($method, $object){
$content = "$this->SIGN_FLAG\nMethod=$method\nBucket=$this->BUCKET\nObject=$object\n";
if($this->IP != ""){
$content .= "Ip=".$this->IP."\n";
}
if($this->TIME != ""){ 
$content .= "Time=".$this->TIME."\n";
}
$sign = "?Sign=$this->SIGN_FLAG:$this->ACCESS_KEY";
return $sign;
}
}
注意:这里Util类继承于Config类,也就继承了Config类中的所有成员变量,故在Util类中可以直接通过$this指针直接访问到配置信息。
TEST CASES
testcases中通过在setUp()函数中new一个Util对象,这样就可以轻松使用lib库中所有方法了,如下:
require_once 'PHPUnit/Framework.php';
require_once 'lib/util.php';

class ObjectPutGET extends PHPUnit_Framework_Testcase{
protected $util;
protected function setUp(){
$this->util = new Util();
}
public function testNormal(){
$object = '/normalObj';
$sign = $this->util->signature("PUT", $object);
$url = $this->util->WEB_SITE.$this->util->BUCKET.$object.$sign;
$http = curl_init();
$infile = fopen("data/file1", "r");
curl_setopt($http, CURLOPT_URL, $url);
curl_setopt($http, CURLOPT_INFILE, $infile);
curl_setopt($http, CURLOPT_INFILESIZE, 8);
curl_setopt($http, CURLOPT_UPLOAD, 1);
curl_exec($http);
curl_close($http);
fclose($infile);
}
}
这里testcases中有一个protect的成员变量$util,并在setUp()中初始化,这样在每个testcase中都可以使用$this->util来访问Util类中的所有方法和变量了。
问题:测试中可能遇到这样的问题,lib库的function依赖于config中的配置,在测试用例中调用function时,又希望能用不同的参数。
解决:按照gtest的测试经验,需要为function提供额外的参数,供传入不同的值。既然使用面向对象了,这里就简单了,只需要通过实例化的lib库调用$this->util->配置项,直接更改配置项信息。如果希望封装好点,可以设置get、set方法分别用于配置项的get和set。
数据驱动
将测试数据保存到data/目录下的相应文件中,通过php unit的dataprovider机制与测试代码结合,将测试数据与用例逻辑解耦合,增加case只需要相应增减数据文件,不需要变更用例逻辑,降低维护成本,提高可扩展性。
/**
* dataprovider for testObjectFileType
*/
public function fileType(){
return array(
array("fputtype.txt", "/putfiletype.txt"),
array("fputtype.docx", "/putfiletype.docx"),
array("fputtype.pdf", "/putfiletype.pdf"),
array("fputtype.xls", "/putfiletype.xls"),
array("fputtype.mp3", "/putfiletype.mp3"),
array("fputtype.mkv", "/putfiletype.mkv"),
array("fputtype.rar", "/putfiletype.rar")
);
}
/**
* 文件,文件类型为txt word excel pdf mp3 mkv rar
* @dataProvider fileType
*/
public function testObjectFileType($fileType, $object_name){
$fileName = $this->util->DATA_DIR.$fileType;
$obj = $object_name;
//put object
$result = $this->util->putObject($fileName, $obj);
$this->assertEquals("", $result);
//get object
$result = $this->util->getObject($obj);
//check
$expect = md5(file_get_contents($fileName));
$actual = md5($result);
$header = new Header(file_get_contents($this->util->HEADER_FILE));
$etag = $header->getETag();
$this->assertEquals($expect, $actual);
$this->assertEquals($expect, $etag);
}
这样组织后,测试用例、配置信息、数据文件以及lib库就解耦了,不管修改哪部分,都可以直接找到并修改,不用担心会对其他case造成什么影响。
A. 编写测试用例,在测试用例根目录下找到对应测试文件,增减相应的case逻辑即可,并且可以在测试用例中轻松调用lib库,动态修改配置信息。
B. 修改数据文件?两步即可,在data目录下增减数据文件,修改对应测试用例的数据驱动信息。
C. 在conf目录中修改配置信息,由于配置信息是全局的,修改已有配置信息需要慎重。
D. lib库与conf一样是全局可见的,修改已有function需要考量对其他case有没有影响。
总结
不仅仅RD的代码需要可扩展性,QA的测试代码同样也需要。
测试也需要设计。

(作者:zhouxiuhu)

 















本文转自百度技术51CTO博客,原文链接:http://blog.51cto.com/baidutech/743445,如需转载请自行联系原作者

相关文章
|
25天前
|
安全 Linux 测试技术
提升龙蜥内核测试能力!探究持续性模糊测试优化实践
清华大学软件学院对Anolis OS使用靶向模糊测试方法将测试工作引向修改的代码,进而提高对业务代码的测试能力。
|
1月前
|
SQL 搜索推荐 测试技术
【Havenask实践篇】完整的性能测试
Havenask是阿里巴巴智能引擎事业部自研的开源高性能搜索引擎,深度支持了包括淘宝、天猫、菜鸟、高德、饿了么在内几乎整个阿里的搜索业务。性能测试的目的在于评估搜索引擎在各种负载和条件下的响应速度、稳定性。通过模拟不同的用户行为和查询模式,我们可以揭示潜在的瓶颈、优化索引策略、调整系统配置,并确保Havenask在用户数量激增或数据量剧增时仍能保持稳定运行。本文举例对Havenask进行召回性能测试的一个简单场景,在搭建好Havenask服务并写入数据后,使用wrk对Havenask进行压测,查看QPS和查询耗时等性能指标。
65385 6
|
2月前
|
安全 测试技术
测试团队的一次复盘实践
测试团队的一次复盘实践
145 0
|
3月前
|
安全 jenkins 测试技术
自动化测试与持续集成/持续交付(CI/CD)的实践与应用
自动化测试是现代软件开发不可或缺的环节,它可以有效地提高测试效率、降低测试成本。而持续集成/持续交付(CI/CD)则是一种基于自动化的软件开发流程,能够将代码的开发、构建、测试和部署等过程无缝连接起来,从而实现快速迭代和部署。本文将结合实际案例,介绍自动化测试和CI/CD的实践与应用。
151 2
|
3月前
|
机器学习/深度学习 搜索推荐 算法
推荐系统离线评估方法和评估指标,以及在推荐服务器内部实现A/B测试和解决A/B测试资源紧张的方法。还介绍了如何在TensorFlow中进行模型离线评估实践。
推荐系统离线评估方法和评估指标,以及在推荐服务器内部实现A/B测试和解决A/B测试资源紧张的方法。还介绍了如何在TensorFlow中进行模型离线评估实践。
194 0
|
10天前
|
敏捷开发 监控 前端开发
深入理解自动化测试框架Selenium的架构与实践
【4月更文挑战第16天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加快迭代速度的关键手段。Selenium作为一种广泛使用的自动化测试工具,其开源、跨平台的特性使得它成为业界的首选之一。本文旨在剖析Selenium的核心架构,并结合实际案例探讨其在复杂Web应用测试中的高效实践方法。通过详细解读Selenium组件间的交互机制以及如何优化测试脚本,我们希望为读者提供深入理解Selenium并有效运用于日常测试工作的参考。
15 1
|
10天前
|
自然语言处理 测试技术 API
深入理解自动化测试框架Selenium的设计理念与实践
【4月更文挑战第15天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加速迭代的关键手段。Selenium作为一种广泛使用的自动化测试框架,提供了对多种浏览器和平台的支持,极大地促进了Web应用的功能测试。本文旨在剖析Selenium的核心设计理念,探讨其在实际项目中的应用,并指出常见的误区及最佳实践,以期帮助测试工程师更高效地利用Selenium进行测试工作。
|
19天前
|
安全 测试技术
深入理解白盒测试:方法、工具与实践
【4月更文挑战第7天】 在软件开发的质量控制过程中,白盒测试是确保代码逻辑正确性的关键步骤。不同于黑盒测试关注于功能和系统的外部行为,白盒测试深入到程序内部,检验程序结构和内部逻辑的正确性。本文将探讨白盒测试的核心技术,包括控制流测试、数据流测试以及静态分析等方法,同时介绍当前流行的白盒测试工具,并讨论如何在实际项目中有效实施白盒测试。文章的目标是为软件测试工程师提供一份综合性指南,帮助他们更好地理解和应用白盒测试技术。
|
1月前
|
敏捷开发 测试技术 持续交付
深入探索软件测试自动化:框架与实践
在快速演进的软件行业中,测试自动化已成为确保产品质量和加快上市速度的关键因素。本文将深入分析测试自动化框架的构建要点,探讨其在实际应用中的效益,以及实施过程中可能面临的挑战。通过对比手动测试与自动化测试的优势与局限,本文旨在为读者提供一套系统化的测试自动化实践指南,以支持更高效、可靠的软件开发周期。
12 0
|
1月前
|
传感器 监控 算法
【软件设计师备考 专题 】模块测试的方法和实践
【软件设计师备考 专题 】模块测试的方法和实践
73 0

热门文章

最新文章