4

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

文件.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;

    }
}

文件上传测试.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)

实用程序文件TransferTest.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%
4

2 回答 2

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 文件之外,您可以轻松访问配置文件或添加其他逻辑。

于 2014-11-10T01:02:40.650 回答
-3

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

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

我们的PHP 测试覆盖率将收集它被告知要跟踪的任何 PHP 脚本中的任何函数的测试覆盖率,无论该函数是如何执行的。它应该可以轻松地提供有关 PHPT 调用的函数执行的覆盖率数据。

于 2011-04-16T04:32:26.733 回答