Web端PHP代码函数覆盖率测试解决方案

1. 有关代码覆盖率

衡量代码覆盖率有很三种档案的次序,举个例子行覆盖率,函数/方法覆盖率,类覆盖率,分支覆盖率等等。代码覆盖率也是权衡测量试验品质的三个要害标准,对于黑盒测量试验来讲,倘使您不分明自身的测量检验用例是还是不是真正跑过了系统内部的每一行代码,在测验的完整性上海市总要打些折扣。由此,产业界差不离对各样编制程序语言都有投机的生机勃勃套代码覆盖率实施方案。世界上最美的语言PHP当然也不例外。PHPUnit和SpikePHPCoverage提供了意气风发套基于xdebug的代码覆盖率测验方案。在本文中,小编将本着本身遇到的一定业务场景,叙述一下和好进行PHP代码函数覆盖率测量试验的解决方案。

版权注脚:本文为博主原创作品,未经博主允许不得转发。

2. 思想政治工作背景

倘使我们在线支付了一个网址,交给工作测量检验的同事去实行功效测量试验。那她们是怎么测量试验的啊?日常意况下,无非是开荒职员把网址安排好了,然后测验人士把英特网具有机能都试用二次,包罗部分充足使用途境。对于事情测量检验来讲,只要自个儿把持有的功效点都测了,把持有极度使用情形也测到了,那就完了了。然而对于开垦来讲,笔者相比较好奇的是,你是或不是把本人写的具有代码都跑到了?会不会设有有的代码,唯有在很奇特的事态下才具接触,而你根本不曾测到过这么些意况?这个时候,大概就须求代码覆盖率来出面了。

骨子里本身第大器晚成想到了xdebug来测验覆盖率,只必要两多少个函数就可以,如下:

xdebug_start_code_coverage(); //开始收集代码行覆盖情况

xdebug_get_code_coverage(); //获取截至目前所跑过的代码文件名和行号

xdebug_stop_code_coverage(); //停止收集代码行覆盖情况

xdebug提供的接口可以用于测实践覆盖率,那是或不是能满意供给呢?其实,行覆盖率颗粒度有一点点细,实际项目中,开拓职员恐怕会对代码实行微调。举个例子,此番测验,你跑过了A.php文件的第10行,可是自身有一天对A.php实行了微调,在A.php第9行和第10行之间又加了两行代码。于是,原本的第10行变为了第12行,而xdebug的行覆盖信息只记录了行号……那样早先的数额岂不是不标准了么。。。考虑一再,笔者以为函数覆盖是个科学的颗粒度。在对峙成熟的体系中,很稀少广大函数变动的状态。不过难点是,xdebug并未提供函数覆盖的接口。

于是乎,大家几日前超过的现象是:

【1】希望测到某次测验中所覆盖的有所函数列表,知道这些类别总结有稍稍个函数,总括一下覆盖率是还是不是充分高。

【2】测量试验完了今后,要生成风度翩翩份覆盖率报告,将代码的遮掩处境可视化。

【3】完整测验的流水生产线如下:

图片 1

里头插桩的意趣是在测验履行在此之前的黄金时代对预备专业。

PHP调节和测验追踪之XDebug使用总计:

3. 函数覆盖率应用方案

(1)原理

xdebug天生提供了对行覆盖率的支撑,我们要本身计算出函数覆盖率。函数覆盖率须求两点数量,叁个是何等函数被施行,一个是文件中总共有多少个函数。

文本中总共的函数量,由于大家不容许把具有函数都实践一遍,因而那部分必须要通过代码静态扫描来兑现。假如是在C++或然Java中,恐怕就需求词法解析工具了,可是在最美的言语PHP日前,大家一同无需那么复杂。从PHP4.3起始,PHP
Zend
Engine中放到了tokenizer效用,援助开拓者做源码词法解析。我们只要求找到PHP中定义函数时所对应的词准则律,就足以轻便收获钦点PHP文件中的全体函数了。

tokenizer定义的接口也非常简便:

array token_get_all (string $source)

该函数实行理文件件深入分析,将php源代码拆成由token组成的数组。

string token_name (int $token)

将整数格局的token转换为字符串方式。相像于C语言中的strerror函数。有了tokenizer,自身再依照php函数定义的原理和格式设计二个点滴状态机,就能够成功全量函数的分析。那有的代码,本人写了个比较简陋的,把它独自拿出来,仅供大家参照他事他说加以考查:PHPFunctionParser

求函数覆盖率的此外四个难题在于获取被试行的函数列表。那地方让我们走了后生可畏部分弯路。意气风发初始一个最轻易易行的措施,大家既然经过xdebug获得被执的行,能够经过行号来反推此行归属哪三个函数。但是每二遍的乞请获取的行号消息量是那些大的,假若二个求情推行了1000行,那将要举行1000次判别,作用上会很倒霉。科研了生龙活虎番自此,发现xdebug提供了function
trace的功能,能够把叁遍呼吁中的函数调用关系取获得,只然则获得了函数名字,却不可能获得它所在的文书。于是,再度调查研讨大器晚成番,开采了Reflection,给定方法名和类名,能够反推出来它在哪些文件中定义。于是大家运用function
trace把函数调用关系暂存在八个一时文件中,然后经过文件解析,获得试行的函数名(借使是类格局,则是“类名::函数名”的样式),再经过reflection机制反推出概念那些函数的文书就能够。再度心获得了世界上最美语言的有力之处。

(2)插桩

为了减少利用门槛,大家尽恐怕少地改成PHP源代码为好。xdebug搜集音信的规律是个别调用xdebug_start_code_coverage和xdebug_stop_code_coverage来决定覆盖率新闻搜聚的启幕和了结,因而不可防止地要改成源代码。此处大家的解除办法是,将xdebug_stop_code_coverage通过register_shutdown_function注册为php程序结束前务供给跑的风流倜傥段程序(相通C语言的atexit函数),将其卷入到贰个文本中,然后在源代码第生机勃勃行require那一个文件就可以。倘诺你的PHP框架是CodeIgniter这种有着央浼都有一个联结入口index.php的框架,那就只须要转移那三个文件就可以,对源代码独有生机勃勃行的改造!实际上,近些日子比较多全数的PHP框架,都以以一个index.php文件作为具备央浼的输入。

咱俩对源代码的修正唯有进口文件index.php的首先行参与了一句话:

require_once "/file/path/to/phpcoverage.php"; ?>

而phpcoverage.php大旨代码逻辑大约如下:

<?php
 ……
function xdebugPhpcoverageBeforeShutdown(){
 ……
 $lineCovData = xdebug_get_code_coverage();
 xdebug_stop_code_coverage();
 ……
 xdebug_stop_trace();
 ……
}
register_shutdown_function(‘xdebugPhpcoverageBeforeShutdown’);
……
xdebug_start_trace(……);
xdebug_start_code_coverage();
//备注:上面省略号表示非关键代码,这里就不展示了

(3)音讯囤积

笔者们的函数覆盖率测量检验有了思路,使用xdebug的function
trace获取三遍呼吁中存有函数的调用关系,获得试行过的保有函数,输出到文件中,通过文件分析和reflection拿到被实行的函数名和该函数所在文书。将那么些新闻存入数据库或文件就可以。

事前试用Spike的时候,大家开采那一个音讯以xml格式存入文件,数据冗余度极高,招致多少个测验下来,文件已经超级大了。那眼看不是我们想看见的。由此在数据存款和储蓄的时候,大家一贯将数据做json格式的种类化,字符串情势存在文件中,大大减弱了文件大小。与此同不经常常候,我们再经过乞求来源的IP和日期作为分隔,分别存储不相同的文书。那样,来自各样机器天天的伸手数据都能胸有定见,向着“精准”的倾向又迈进了一步,能够对测量检验职员的各种须求做纯粹的督察。下图是大家在业务推行中募集的风度翩翩对数据文件截图:

图片 2

诸如此比,来自其余三个IP的每三次Web央浼,它所覆盖的行和函数信息,都会被记录到文件中。对于平时的连串测量检验中,也就独有多少个测量试验职员在利用,所以无需思谋部分品质难点。

Xdebug是多个开源的PHP程序调节和测量试验工具,能够应用它来调整、追踪及分析程序运维情形。当然,Xdebug须要整合PHP的编排工具来打断点、追踪、调试及剖判,相比常用的PHP的Xdebug调节和测量检验情形:Vim
+Xdebug。

4. 告知生成

地点讲了转移覆盖率数据的法规,可是我们于今得到的只是风华正茂份份的数据文件,怎么着聚焦成风流罗曼蒂克份完整的告诉呢?那就须要大家团结来写意气风发段脚本深入解析刚才生成的数据文件了。大家的做法是以人为镜了开源工具spike
phpcoverage的模板,并参与动和自动己的代码逻辑,极其是步向了该工具所不持有的函数覆盖率总结数据。大家友好测验的web页素不相识成的告知如下:

图片 3

图中得以看见各种文件的行覆盖率,函数覆盖率,还恐怕有总的覆盖率计算数据。假使急需更规范的数额,能够点进文件三番三回,查看终究覆盖的是什么代码行(巴黎绿为掩盖,铅白为未覆盖):

图片 4

 

5. 总结

业务测验中做Web测验时,对代码的覆盖率是衡量测量检查验质量量的首要指标。我们愿意经过此办法成功尽量地“精准”,测量试验施行完后能够确切见到哪大器晚成行代码被试行过,哪风华正茂行没被实践过。分析没被试行过的原故,进而改善测量检验用例。使用工具的流水生产线也很简短,插桩=>测量检验=>采撷数据=>出报告。而且此技术方案最大化地回降了对专门的事业代码的熏陶,只必要改大器晚成行代码就可以。纵然中间现身了难点,也能够神速将代码苏醒为原貌。让测验放心,让开辟也放心。

不过,最终还亟需强调的一些是,并非说覆盖了富有的代码,就表明测量试验已经完全了。只可是没被蒙蔽的话,一定是不完全的。所以这些方案最大的意义在于能够发掘测验中一些漏掉的代码,找到后生可畏都部队分难点。其实,它也可以帮忙新来的工作者了然整个项目代码构造,我们可以清晰的知晓,本人的每回浏览器伏乞,到底在运维服务器上的怎么代码。

·     安装配备

·     调节和测量检验景况

·     追踪深入分析

·     注意事项

·     遇到难题

 

意气风发、安装配备

1、安装

Xdebug的设置是用作PHP的进行而存在的,所以可参看PHP扩充小说:

 

2、配置

php.ini:

[xdebug]

;基本调节和测验配置

xdebug.auto_trace = on

xdebug.collect_params = on

xdebug.collect_return = on

xdebug.profiler_enable = on

xdebug.profiler_output_dir =”/php/ext/xdebug_profilers”

xdebug.trace_output_dir = “/tmp/ext/xdebug_traces”

;远程调节和测验设置

xdebug.remote_enable = on

xdebug.remote_host = localhost

xdebug.remote_port = 9010

xdebug.remote_autostart = on

 

zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so

 

NOTE:

地方罗列的是极端常用的陈设选项,至于别的安顿选项及相应的意思,请参见:

 

二、调节和测验情状

Vim + Xdebug:

1、下载

2、配置

$ cd  ~

$ sudo mkdir ~/.vim

将地点下载的xdebug的plugin中文件复制到.vim下:

$ sudo cp –r /php/ext/plugin  .

在客户主目录下创制.vimrc文件:

$ sudo touch /usr/share/vim/vimrc  ~/.vimrc

$ sudo vim ~/.vimrc

为.vimrc增多以下内容:

let g:debuggerPort = 9010(该端口必需与xdebug.remote_port相同)

let g:debuggerMaxDepth = 5(代表数组调节和测量检验深度配置)

 

NOTE:

vimrc文件是vim的尤为重要布局文件,它满含三个版本:全局版本和客户版本,大家建议修正顾客版本的vimrc配置文件,这二种版本的不二等秘书技可在vim普通情势下查看,如下:

 

大局版本路线查看:

$ sudo vim

$ :echo $VIM

路径地址:/usr/share/vim

 

顾客版本路线查看:

$ sudo vim

$ :echo $HOME

路径地址:$HOME(pwd ~)

 

注意:

g:debuggerPort的端口号,必需与xdebug.remote_port相同;

g:debuggerMaxDepth代表的是本子调试的最大深度等级次序;

 

末段,改正完php.ini、.vimrc配置后,记得重启php-fpm。

 

3、调试

A、准备贰个php文件

<?php

 $value = ‘马上采用XDebug调节和测量检验程序,你筹划好了吗’;

 echo $value;

?>

将下边包车型地铁公文纳入到您的Web根目录下,我的寻访地址是:

 测验下是不是正规呈现。

 

B、使用vim打开php文件

利用vim普通形式打开php文件,移动鼠标箭头到欲调节和测验的那行,输入:

$:Bp

截图如下:

图片 5

然后,按下F5(Mac:Fn+F5卡塔尔(قطر‎,开端监听调试事件,那时候在编写制定窗尾巴部分提醒5秒内访谈要调整的php文件,举个例子:

? XDEBUG_SESSION_START=1

 

截图如下:

图片 6

对此调节和测量检验中的操作在下面附加上:

类型

功能

说明

<Command Mode>

 

 

:Bp

 toggle breakpoint

断点标记

:Up

 stack up

 

:DN

 stack down

 

<Normal Mode>

 

 

,e

 eval

 

<Function Keys>

 

 

F1

 resize

调整窗口大小

F2

 step into

调试步进入

F3

 step over

调试步进入下一标记

F4

 step out

调试步出当前标记

F5

 run

调试运行

F6

 quit debugging

退出调试模式

F11

 get all context

获得所有变量内容

F12

 get property of cursor

获得当前光标变量

 

 

三、追踪分析

1、代码覆盖深入分析

Xdebug
2.2上马援助对代码覆盖的分析,相当于透过对代码的覆盖解析,大家得以精通到在IDE访问时期,有哪些代码行数被施行了,有利于对大旨代码和单元测量试验有指向的打听和解析,最后提升代码的品质。

A、涉及的配置

xdebug.coverage_enable=1

//该配置默以为1,也正是暗中认可开启,假使设置为0,代码的覆盖剖析就不会开展。

 

B、涉及的函数

boolean xdebug_code_coverage_started()

//该函数重回布尔值,用来剖断代码覆盖深入分析效果与利益是还是不是开启,未展开则赶回false。

 

void xdebug_start_code_coverage( [int options] )

//该函数未有别的再次来到,它的功用是初阶征集解析结果集数据,数据是以二维数组时势//存在,朝气蓬勃维参数为剖析的文书名字,二维参数为相应的分析行数;别的,在言之有序文件

//的每行代码时,都会时有发生叁个结出码,如下:

//1:代表代码已经施行;

//-1:代表代码未被推行,对应函数参数XDEBUG_CC_UNUSED传入;

//-2:代表未有可实施的代码存在,对应XDEBUG_CC_DEAD_CODE和XDEBUG_CC_UNUSED

 

NOTE:

XDEBUG_CC_UNUSED:用来测算剖判时满含搜集未被实施的代码;

XDEBUG_CC_DEAD_CODE:用来测算深入分析时期码行是不是被试行;

 

款式如下:

xdebug_start_code_coverage(XDEBUG_CC_UNUSED|XDEBUG_CC_DEAD_CODE);

 

array xdebug_get_code_coverage()

//该函数重返数组值,用来访问和重回代码覆盖解析的结果集音讯。

 

void xdebug_stop_code_coverage( [int cleanup=true] )

//该函数不回去任何值,用来终止覆盖分析,即使传入参数为true,那么就能够告生机勃勃段落解析并清空内部存款和储蓄器中的解析结果集,否者传入false,反之,还可使用//xdebug_start_code_coverage找回该内部存款和储蓄器信息。

 

C、示例的求证

Php代码:

<?php

echo ‘覆盖深入分析实行中…</br>’;

 

// 构建封装对象

class XdebugCoverageAnalysisModel {

      private $_coverage_info;

      private $_status;

 

      function __construct() {

          $this->_coverage_info = xdebug_get_code_coverage();

          $this->_status =xdebug_code_coverage_started();

        }

 

      // 获取剖析结果

      public functiongetCodeCoverageResult() {

           returnjson_encode(xdebug_get_code_coverage());

      }

 

      // 开启覆盖解析

      public functionxdebugStartCodeCoverage() {

            xdebug_start_code_coverage( -1 | -2 );

        }

 

      // 剖析是或不是试行

      public functionxdebugCodeStarted() {

           return xdebug_code_coverage_started();

      }

}

 

// 初始化

$apiModel = new XdebugCoverageAnalysisModel();

 

echo ‘开启覆盖剖判…</br>’;

$apiModel->xdebugStartCodeCoverage();

 

// 定义三个测量试验函数

function coverageSample($a,$b) {

   echo ‘函数结出:’.($a * $b).'</br>’;

}

 

echo ‘判定是还是不是开启…</br>’;

$status = $apiModel->xdebugCodeStarted();

if($status==’1′) {

  echo ‘开启覆盖剖析已形成</br>’;

} else {

  echo ‘开启覆盖分析退步了</br>’;

}

 

echo ‘测量检验函数开启…</br>’;

coverageSample(10,10);

 

echo ‘获取分析结果…</br>’;

$result = $apiModel->getCodeCoverageResult();

echo $result.'</br>’;

 

echo ‘关闭分析按钮…</br>’;

xdebug_stop_code_coverage();

 

$status = $apiModel->xdebugCodeStarted();

if($status==’1′) {

  echo ‘覆盖解析已经达成</br>’;

} else {

  echo ‘覆盖分析已经破产!</br>’;

}

 

unset($result);

unset($apiModel);

 

?>

 

浏览器结果:

图片 7

 

2、PHP脚本深入分析

Xdebug的PHP脚本剖判效果与利益相比实用,它能够扶助我们深入分析代码的瓶颈和熏陶属性缓慢的标题,为优化代码提供方向的参照他事他说加以考查。

 

A、涉及的布署

xdebug.profiler_enable

//该配置默以为0,为展开,设置为非0之后,即张开profiler成效

xdebug.profiler_output_dir

//该配置为地点开启之后,存放生成剖析文件之处,要求确认保证地方可写入,暗中认可/tmp

xdebug.profiler_enable_trigger

//倘使翻开该接纳,则在历次乞请中后生可畏经GET/POST或cookie中包罗//XDEBUG_PROFILE变量名,则才会扭转品质报告文本(前提是必须关闭

//xdebug.profiler_enable选项,不然该选项不起效用卡塔尔(قطر‎。

xdebug.profiler_output_name

//能够采取该配置校订生成的剖析文件,暗中同意cachegrind.out.%p

 

NOTE:

提出选择xdebug.profiler_enable_trigger替代xdebug.profiler_enable

 

B、涉及的函数

string xdebug_get_profiler_filename()

//再次回到类型为字符串,用来回到深入分析的公文名字

 

C、示例的求证

当大家张开深入分析开关之后,当有脚本运营就能够在钦赐的岗位生成格式为cachegrind.out.xxx的解析文件:

图片 8

该文件的内容不是很直观,所以要求利用可视化的工具来查看和剖判,而Xdebug本人就支持选用第三方的可视化profiler文件的内容。在Linux下,能够运用KCacheGrind,而在Windows平台,能够运用QCacheGrind,当然还应该有生龙活虎对在线的由发烧友开荒的工具,譬喻:WebGrind,具体怎么利用这个工具,能够参照:

上面罗列下,WebGrind的效果与利益:

图片 9

 

WebGrind能够在这里地下载:

 

四、注意事项

1、制止生育条件开启profiler和trace,只需开启远程调节和测量检验;

2、尽量选择xdebug.profiler_enable_trigger替代xdebug.profiler_enable;

3、假若应用webgrind分析profiler,提出并非放入坐蓐意况,因为其并未有安全范围,任什么人都能够访谈;

4、Xdebug的法力即使强盛,可是要均衡质量费用;

 

五、境遇标题

问题:Error(“DbgProtocol instance has no attribute ‘stop'”,)

产生该难点的缘故大约如下:

A、配置文件配置不正确;

B、.vimrc和php.ini中的port不相同;

C、.vimrc和php.ini中的port与存活的port冲突;

解决:

比较上边的几条明细查阅配置就可以。

 

NOTE:

有博客说因为未在U冠道L后增多XDEBUG_SESSION_START=1,其实不然。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注