原理很简单,利用debug.sethook可以得到代码执行情况,然后再用phpunit来生成html版本的覆盖率报告出来
直接上两个代码首先是CodeCoverage.lua
module("CodeCoverage", package.seeall) local mResult = nil local mRunninng = false local mPrefix = nil local mPrefixLen = 0 local function execCallback(event, line) if line == 0 or event ~= "line" or mResult == nil then return end local source = debug.getinfo(2, "S").source if mPrefixLen > 0 then local prefix = source:sub(1, mPrefixLen) if prefix ~= mPrefix then return end if mPrefix == "@" then source = source:sub(2) end end if mResult[source] == nil then mResult[source] = { [line] = 1 } elseif mResult[source][line] == nil then mResult[source][line] = 1 end end function start(prefix) if mRunning then return end debug.sethook(execCallback, 'l') mPrefix = prefix if mPrefix ~= nil then mPrefixLen = mPrefix:len() else mPrefixLen = 0 end if mResult == nil then mResult = {} end mRunning = true end function stop(file) debug.sethook() mRunning = false if file ~= nil then save(file) end end function save(file) if mResult == nil then return false end local f = io.open(file,'w') for source, lines in pairs(mResult) do for line, count in pairs(lines) do f:write(string.format("%s %d %d\n", source, line, count)) end end f:close() mResult = nil return true end
define ( 'PREFIX', "/home/pirate/sgres/Resources/" ); function generate() { $coverage = new PHP_CodeCoverage (); $dir = opendir ( COV_ROOT ); if (empty ( $dir )) { echo COV_ROOT . " can't be opened, please check if it exists\n"; return; } $arrCoverage = array (); $arrFile = array (); while ( true ) { $file = readdir ( $dir ); if (empty ( $file )) { break; } if ($file == '.' || $file == '..') { continue; } $file = COV_ROOT . '/' . $file; $arrFile [] = $file; $fh = fopen ( $file, 'r' ); $arrData = array (); while ( ! feof ( $fh ) ) { $line = fgets ( $fh ); $arrLine = explode ( ' ', $line, 3 ); if (count ( $arrLine ) != 3) { continue; } $source = $arrLine [0]; $lineno = $arrLine [1]; $flag = $arrLine [2]; if (substr ( $line, 0, 1 ) != "/") { $source = PREFIX . $source; } if (! file_exists ( $source )) { continue; } $arrData [$source] [$lineno] = $flag; } fclose ( $fh ); if (empty ( $arrCoverage )) { $arrCoverage = $arrData; continue; } foreach ( $arrData as $file => $arrLine ) { if (! isset ( $arrCoverage [$file] )) { $arrCoverage [$file] = $arrLine; continue; } foreach ( $arrLine as $line => $flag ) { if (! isset ( $arrCoverage [$file] [$line] )) { $arrCoverage [$file] [$line] = $flag; continue; } if ($arrCoverage [$file] [$line] < $flag) { $arrCoverage [$file] [$line] = $flag; } } } } if (count ( $arrFile ) > 1) { $time = intval ( microtime ( true ) * 1000 ); $filename = COV_ROOT . '/' . $time . '.cov'; $fh = fopen ( $filename, 'w+' ); foreach ( $arrCoverage as $source => $arrLine ) { foreach ( $arrLine as $line => $flag ) { fprintf ( $fh, "%s %d %d\n", $source, $line, $flag ); } } fclose ( $fh ); foreach ( $arrFile as $file ) { unlink ( $file ); } } foreach ( $arrCoverage as $source => &$arrLine ) { $fh = fopen ( $source, 'r' ); $i = 0; $inFunc = false; $funcStart = 0; $funcEnd = 0; $inComment = false; $commentCount = 0; while ( ! feof ( $fh ) ) { $i ++; $line = fgets ( $fh ); $line = trim ( $line ); // 过滤空行 if ($line == "") { continue; } // 过滤未执行函数 if (isset ( $arrLine [$i] )) { if (! $inFunc) { if (substr ( $line, 0, 9 ) == "function ") { $inFunc = true; $funcStart = $i; } } else { if (substr ( $line, 0, 3 ) == "end") { $funcEnd = $i; for($j = $funcStart; $j <= $funcEnd; $j ++) { $arrLine [$j] = - 1; } } $inFunc = false; } } else { // 过滤注释 $prefix = substr ( $line, 0, 4 ); if (! $inComment) { if ($prefix == '--[[') { $inComment = true; $commentCount = 1; continue; } if (substr ( $line, 0, 2 ) == "--") { continue; } } else { if ($prefix == '--[[') { $commentCount ++; } else if ($prefix == '--]]') { $commentCount --; if ($commentCount == 0) { $inComment = false; } } continue; } $arrLine [$i] = - 1; } } fclose ( $fh ); } $coverage->append ( $arrCoverage, 'cov' ); $generator = new PHP_CodeCoverage_Report_HTML (); $generator->process ( $coverage, COVERAGE_ROOT ); echo sprintf ( "generate cov file in '%s' to '%s', done\n", COV_ROOT, FrameworkConfig::COVERAGE_ROOT ); } generate ();