我如何得到php代码覆盖运行在php测试用例


file upload - How do I get php code coverage to run over phpt test cases?

我有一个运行产品组件测试的测试环境。我发现最近很难测试和成功模拟php的is_uploaded_file()move_uploaded_file(),但经过大量的搜索和研究,我找到了PHPT。这对我测试这些方法和文件上传的期望有很大帮助。这不是一个关于文件上传的问题,而是如何将phpt测试用例集成到基本的phpunit测试用例中,以便对正在测试的方法也运行代码覆盖。下面是一些代码摘录:

files.php

class prFiles
{
    // Instance methods here not needed for the purpose of this question
    // ......
    public function transfer(array $files, $target_directory,
        $new_filename, $old_filename = '')
    {
        if ( (isset($files['file']['tmp_name']) === true)
            && (is_uploaded_file($files['file']['tmp_name']) === true) )
        {
            // Only check if old filename exists
            if ( (file_exists($target_directory . '/' . $old_filename) === true)
                && (empty($old_filename) === false) )
            {
                unlink($target_directory . $old_filename);
            }
            $upload = move_uploaded_file(
                $files['file']['tmp_name'],
                $target_directory . '/' . $new_filename
            );
            if ( $upload === true )
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        return false;
    }
}

file_upload_test.phpt

--TEST--
Test the prFiles::transfer() the actual testing of the file uploading.
--POST_RAW--
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryfywL8UCjFtqUBTQn
------WebKitFormBoundaryfywL8UCjFtqUBTQn
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
This is some test text
------WebKitFormBoundaryfywL8UCjFtqUBTQn
Content-Disposition: form-data; name="submit"
Upload
------WebKitFormBoundaryfywL8UCjFtqUBTQn--
--FILE--
<?php
require_once dirname(__FILE__) . '/../../../src/lib/utilities/files.php';
$prFiles = prFiles::getInstance()->transfer(
    $_FILES,
    dirname(__FILE__) . '/../_data/',
    'test.txt'
);
var_dump($prFiles);
?>
--EXPECT--
bool(true)

UtilitiesFilesTransferTest.php

class UtilitiesFilesTransferTest extends PHPUnit_Extensions_PhptTestCase
{
    /**
     * Constructs a new UtilitiesFilesTransferTest.
     *
     */
    public function __construct()
    {
        parent::__construct(dirname(__FILE__) . '/_phpt/file_upload_test.phpt');
    }
}

这样就可以了。但是我似乎无法得到任何关于我正在测试的传输方法的报道。有人能帮帮我吗?

编辑:我的覆盖命令看起来像这样:

@echo off
echo.
if not "%1"=="" goto location
goto default
:location
set EXEC=phpunit --coverage-html %1 TestSuite
goto execute
:default
set EXEC=phpunit --coverage-html c:'xampp'htdocs'workspace'coverage'project TestSuite
:execute
%EXEC%

由于PhpUnit具有在单独进程中运行PHPT文件的自定义实现,因此将代码覆盖与PhpUnit集成可能会被证明是相当困难的。

然而,如果你所需要的只是覆盖(或者你愿意自己做一些后期处理),这就变得相当微不足道了。

在最简单的形式中,您所需要做的就是从php文件中调用xDebug。使用PHP_CodeCoverage(和Composer用于类自动加载),您的--FILE--部分可能看起来像这样:
--FILE--
<?php
/* autoload classes */
require __DIR__ . '/../../../vendor/autoload.php';
/* Setup and start code coverage */
$coverage = new 'PHP_CodeCoverage;
$coverage->start('test');
/* run logic */
$prFiles = prFiles::getInstance()->transfer(
    $_FILES,
    __DIR__ . '/../_data/',
    'test.txt'
);
var_dump($prFiles);

/* stop and output coverage data */
$coverage->stop();
$writer = new 'PHP_CodeCoverage_Report_PHP;
$writer->process($coverage, __DIR__ . '/../../../build/log/coverage-data.php');
?>

将收集到的所有覆盖率数据放入coverage-data.php文件中。

你可以加载这些信息,并将其与其他覆盖信息(例如来自PhpUnit)结合起来,以任何你想要的格式创建输出。

覆盖逻辑可以放在一个单独的类中,只留下两行添加到您想要覆盖的每个测试中:

--FILE--
<?php
/* autoload classes */
require __DIR__ . '/../../../vendor/autoload.php';
cover::start;
/* run logic */
$prFiles = prFiles::getInstance()->transfer(
    $_FILES,
    __DIR__ . '/../_data/',
    'test.txt'
);
var_dump($prFiles);
cover::stop;
?>

cover类:

<?php
class cover
{
    private static $coverage;
    /* Setup and start code coverage */
    public static function start()
    {
        self::$coverage = new 'PHP_CodeCoverage;
        /* Make sure this file is not added to the coverage data */
        $filter = self::$coverage->filter();
        $filter->addFileToBlacklist(__FILE__);
        self::$coverage->start('test');
    }
    /* stop and output coverage data */
    public static function stop()
    {
        self::$coverage->stop();
        $writer = new 'PHP_CodeCoverage_Report_PHP;
        $writer->process(self::$coverage, __DIR__ . '/../build/log/coverage-data.php');
    }
}   

由于覆盖逻辑位于PHPT文件之外,您可以轻松访问配置文件或添加其他逻辑。

我不太清楚为什么PHPUnit不为您收集这些覆盖率数据。这可能与它如何使用(或不使用)XDebug有关。

您可以通过使用不依赖于PHPUNit或XDebug工作方式的测试覆盖工具来解决这个问题。

我们的PHP测试覆盖将收集它被告知跟踪的任何PHP脚本中任何函数的测试覆盖,不管该函数是如何执行的。提供PHPT调用的函数执行的覆盖率数据应该没有问题。