PHP代码覆盖率统计详解


Posted in PHP onJuly 22, 2020

一 安装php环境

二 统计php代码覆盖率

1 需要安装xdebug

安装步骤:

测试环境

  • LNMP 军哥一键包1.3版本
  • PHP 7.0.7
  • Xdebug 2.6

配置步骤

git clone git://github.com/xdebug/xdebug.git
cd xdebug
find / -name phpize
/usr/bin/phpize
find / -name php-config
./configure --enable-xdebug --with-php-config=/usr/local/php/bin/php-config
make
make install

开启扩展

find / -name php.ini
vi /usr/local/php/etc/php.ini
添加 extension=xdebug.so
[Xdebug]
xdebug.collect_params=on
xdebug.collect_return=on
xdebug.remote_autostart=on

service restart php-fpm

成功验证:①在linux输入php -version,如下:

PHP代码覆盖率统计详解

②访问index.php(phpinfo())

PHP代码覆盖率统计详解

2 安装composer

curl -sS https://getcomposer.org/installer | php
php composer.phar --version
Composer version 1.6.5 2018-05-04 11:44:59

3 安装phpcov 和 phpunit

此处选了phpunit 6.5.0 和phpcov 4.0.8,编辑composer.json文件(phpcov是根据phpunit自动匹配的,php和phpunit对应关系可百度或看底部)

#composer.json
{
 "name": "root/php-code-coverage",
 "require-dev": {
 "phpunit/phpunit":"6.5.0",
 "phpunit/phpcov": "*"
}

执行命令安装 php composer.phar install

安装完成后校验 如下即可(phpunit和phpcov一定要在这个目录下使用)

vendor/bin
[root@mt-jry-01 bin]# ll
lrwxrwxrwx 1 root root 24 Jul 13 10:22 phpcov -> ../phpunit/phpcov/phpcov
lrwxrwxrwx 1 root root 26 Jul 13 10:21 phpunit -> ../phpunit/phpunit/phpunit
[root@mt-jry-01 bin]# .vendor/bin/phpunit --version
PHPUnit 6.5.0 by Sebastian Bergmann and contributors.
 
[root@mt-jry-01 bin]# .vendor/bin/phpcov --version
phpcov 4.0.5 by Sebastian Bergmann.

4 编写测试代码

#userinfo.php
<?php
include_once("*****/prepend.php"); 
$id = $_POST["user_id"];
if ($id != 10086){
 exit();
}
$userinfo = array(
 'username'=>'jason',
 'password'=>'123456',
);
$result = array(
  'code'=>10000,
  'message'=>"success",
  'data'=>$userinfo,
 );
echo json_encode($result);
#prepend.php
<?php
require_once dirname(__FILE__).'/vendor/autoload.php'; # 在composer生成的vender同级目录
use SebastianBergmann\CodeCoverage\CodeCoverage;
$coverage = new CodeCoverage;
 
$coverage->filter()->addDirectoryToWhitelist('/var/www/html/userinfo.php'); # 白名单<br>$coverage->filter()->removeDirectoryFromWhitelist('/var/www/html/userinfo.php'); # 从白名单中移除文件夹<br>$coverage->filter()->removeFileFromWhitelist('/var/www/html/userinfo.php'); # 从白名单中移除文件
$coverage->start('<Site coverage>');#开始统计
register_shutdown_function('__coverage_stop',$coverage);#注册关闭方法
 
function __coverage_stop(CodeCoverage $coverage){
 $coverage->stop();#停止统计
 $cov = '<?php return unserialize(' . var_export(serialize($coverage), true) . ');';#获取覆盖结果,注意使用了反序列化
 //echo $cov;
 file_put_contents(dirname(__FILE__).'/cov/site.' . date('U') .'.'.uniqid(). '.cov', $cov);#将结果写入到文件中
}
 
若多个域名或者接口请求要在同一个prepend文件里分别统计,在新建$coverage前加if条件即可,如
if(strpos($_SERVER['HTTP_HOST'],'www.baidu.com') === true){}

5 测试

执行命令

[root@mt-jry-01 html]# curl -d "user_id=10086" "127.0.0.1/userinfo.php"
{"code":10000,"message":"success","data":{"username":"jason","password":"123456"}}

查看prepend.php统计目录cov下

-rw-r--r-- 1 apache apache 4609 Jul 13 14:45 site.1531464305.5b484a71c0a1c.cov

生成xml或者html报告命令如下:

./vendor/bin/phpcov merge --clover cov/coverage.xml cov/ -vvv # 在cov目录下生成xml报告
./vendor/bin/phpcov merge --html="cov/coverage_html" cov/ -vvv # 在cov目录下生成html报告 

6 查看报告结果

PHP代码覆盖率统计详解

8 工程配置

在实际项目中有三种配置方式

  1. 在php.ini中引入prepend文件:auto_prepend_file = /***/prepend.php (配置后重启php) --- 所有php请求均会预加载该文件,文件有错误时影响整个php服务
  2. 在文件入口文件中引入prepend文件:include_once(/www/***/prepend.conf); (一般为index.php) --- 效果同3,重新部署清掉配置
  3. 在nginx.conf中引入prepend文件 --- 对于该域名的请求会加载该文件(配置后重启nginx)
location ~ .*\.php?$
{ 
 fastcgi_pass 127.0.0.1:9200;
 fastcgi_index index.php;
 include common/fastcgi.conf;
 fastcgi_param MY_ENV pre;
 fastcgi_param PHP_VALUE 'auto_prepend_file=/www/data/phpcoverage/prepend.php';
}
 

7 问题:

① 开始使用的phpcov 2.0.2 & phpunit 4.8.7 生成的报告数据全为0 - phpunit4 不能支持 php7,对应版本见⑦

② 开始总是报错PHP Fatal error: Uncaught Error: Class 'SebastianBergmann\CodeCoverage\CodeCoverage' not found in

是因为没有引用vender目录,在prepend.php里加一句require_once dirname(__FILE__).'/vendor/autoload.php'; 即可

③ 配置nginx

④ 请求域名没有生成site文件:请求权限不够,不能在对应目录下写文件

chmod 777 -R 域名请求是apache权限,如果与cov文件夹权限不一致则不可写入

⑤ 生成覆盖率文件有要统计的代码文件,但是命中情况count全为0,有两种可能

A xdebug的collect_param 与collect_return没打开,导致未收集到数据,需要在php.ini里配置

B 如果在php.ini里配置了auto_prepend_file=‘**/prepend.php',则只有用指定目录下的prepend.php文件才能生成覆盖率数据,否则覆盖行全为0

⑥ 将xml报告集成到jenkins

注意:go 和 c++ 的xml报告可以用 Cobertura 统计到jenkins展示,php 的要用Clover PHP 插件统计,phpcov生成的xml格式Cobertura解析不了会报错

⑦ php 和 phpunit 的对应关系https://phpunit.de/supported-versions.html

PHP代码覆盖率统计详解

⑧ 问题:观察每日构建的覆盖率,在代码未更新,用例未更新的前提下,覆盖率降低

  1. 该方式统计的代码总行数变化,与之前不一致 -- 实际两天的代码完全一致
  2. 同一个文件的覆盖行数不一致,发现会出现同一个分支中,上下行未覆盖,而中间行覆盖 和 空行被覆盖(空白行 绿色,鼠标放置提示 1test covers..)的

原因:猜测是 xdebug 统计抽风,因为 xdebug 负责收集统计代码,phpunit phpcov只是汇总整理为可读报告。

解决:暂不能解决,可观察xdebug和phpcoverage官网有类似问题

⑨ jenkins 配置

cur_path=`pwd`
echo ${cur_path}
 
# 删除历史cov文件,保证覆盖率干净
find /www/data/phpcoverage/admin_cov/ -name "site*" | xargs rm -rf
rm -rf ${cur_path}/reports/*
 
#在工程入口文件引入 prepend 文件
sed -i '2cinclude_once("/www/data/phpcoverage/prepend.php");' /www/my_project/index.php
 
# 更新自动化用例并执行用例
source /www/data/project3/venv/bin/activate
git checkout master
git pull
python run.py
 
# 统计html和xml报告,html更易读,xml更直观反映历史情况
cd /www/data/phpcoverage
./vendor/bin/phpcov merge --clover ${cur_path}/reports/coverage.xml admin_cov/ -vvv
./vendor/bin/phpcov merge --html="${cur_path}/reports/coverage_html" admin_cov/ -vvv
 
# 从入口文件删除引用
sed -i '2c//' /www/my_project/index.php

https://github.com/sebastianbergmann/phpcov

到此这篇关于PHP代码覆盖率统计详解的文章就介绍到这了,更多相关PHP代码覆盖率内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
PHP获取当前文件所在目录 getcwd()函数
May 13 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
Mar 05 PHP
使用array_map简单搞定PHP删除文件、删除目录
Oct 29 PHP
PHP统计目录大小的自定义函数分享
Nov 18 PHP
php多次include后导致全局变量global失效的解决方法
Feb 28 PHP
php输出全球各个时区列表的方法
Mar 31 PHP
详解PHP错误日志的获取方法
Jul 20 PHP
PHP常见数组函数用法小结
Mar 21 PHP
Laravel如何友好的修改.env配置文件详解
Jun 07 PHP
php框架CodeIgniter使用redis的方法分析
Apr 13 PHP
微信公众平台开发教程①获取用户Openid及个人信息图文详解
Apr 10 PHP
php异常处理捕获错误整理
Sep 23 PHP
php实现统计IP数及在线人数的示例代码
Jul 22 #PHP
Yii使用DbTarget实现日志功能的示例代码
Jul 21 #PHP
浅谈PHP之ThinkPHP框架使用详解
Jul 21 #PHP
浅谈php常用的7大框架的优缺点
Jul 20 #PHP
KindEditor在php环境下上传图片功能集成的方法示例
Jul 20 #PHP
php连接mysql之mysql_connect()与mysqli_connect()的区别
Jul 19 #PHP
PHP+MySql实现一个简单的留言板
Jul 19 #PHP
You might like
如何隐藏你的.php文件
2007/01/04 PHP
自己写的php curl库实现整站克隆功能
2015/02/12 PHP
浅谈PHP接收POST数据方式
2015/06/05 PHP
php实现比较全的数据库操作类
2015/06/18 PHP
php+mysql实现的二级联动菜单效果详解
2016/05/10 PHP
PHP fprintf()函数用法讲解
2019/02/16 PHP
msn上的tab功能Firefox对childNodes处理的一个BUG
2008/01/21 Javascript
用jQuery简化JavaScript开发分析
2009/02/19 Javascript
javascript 时间比较实现代码
2009/10/28 Javascript
javascript 按回车键相应按钮提交事件
2009/11/02 Javascript
TinyMCE 新增本地图片上传功能
2010/11/05 Javascript
JS实现点击图片在当前页面放大并可关闭的漂亮效果
2013/10/18 Javascript
javascript事件冒泡和事件捕获详解
2015/05/26 Javascript
JavaScript地理位置信息API
2016/06/11 Javascript
JavaScript中自带的 reduce()方法使用示例详解
2016/08/10 Javascript
纯js实现倒计时功能
2017/01/06 Javascript
Bootstrap框架建立树形菜单(Tree)的实例代码
2017/10/30 Javascript
Phaser.js实现简单的跑酷游戏附源码下载
2018/10/26 Javascript
Vue实现点击当前元素以外的地方隐藏当前元素(实现思路)
2019/12/04 Javascript
windows下python连接oracle数据库
2017/06/07 Python
Django中Model的使用方法教程
2018/03/07 Python
python3获取两个日期之间所有日期,以及比较大小的实例
2018/04/08 Python
Python使用numpy模块实现矩阵和列表的连接操作方法
2019/06/26 Python
Python PyPDF2模块安装使用解析
2020/01/19 Python
Tensorflow安装问题: Could not find a version that satisfies the requirement tensorflow
2020/04/20 Python
Python局部变量与全局变量区别原理解析
2020/07/14 Python
一篇文章带你学习CSS3图片边框
2020/11/04 HTML / CSS
汉森批发:Hansen Wholesale
2018/05/24 全球购物
阿巴庭院:Abba Patio
2019/06/18 全球购物
Keds加拿大官网:购买帆布运动鞋和皮鞋
2019/09/26 全球购物
售后服务经理岗位职责
2014/02/25 职场文书
企业安全生产责任书范本
2014/07/28 职场文书
杨善洲电影观后感
2015/06/04 职场文书
关于空气污染危害的感想
2015/08/11 职场文书
2016教师学习教育法心得体会
2016/01/19 职场文书
Python 读取千万级数据自动写入 MySQL 数据库
2022/06/28 Python