如何获得php代码覆盖率来运行phpt测试用例?

时间:2011-04-11 14:03:37

标签: php file-upload phpunit code-coverage phpt

我有一个运行产品组件测试的测试环境。我发现最近很难测试并成功模拟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');

    }

}

这样一切顺利。但我似乎无法覆盖我正在测试的传输方法。请有人帮帮我吗?

编辑:我的coverage命令如下所示:

@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%

2 个答案:

答案 0 :(得分:1)

由于PhpUnit具有在单独进程中运行PHPT文件的自定义实现,因此使用PhpUnit获取代码覆盖集成可能会非常困难。

但是,如果您只需要覆盖(或者您愿意自己进行一些后期处理),那就变得非常简单。

以最简单的形式,您需要做的就是从PHPT文件调用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文件之外,您可以轻松访问配置文件或添加其他逻辑。

答案 1 :(得分:-3)

我不明白为什么PHPUnit不会为您收集此覆盖数据。它可能与它如何使用(或不使用)XDebug有关。

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

我们的PHP Test Coverage将收集任何已被告知要跟踪的PHP脚本中的任何函数的测试覆盖率,无论该函数的执行方式如何。它可以毫无困难地提供有关PHPT调用的函数执行的覆盖数据。