我有一个运行产品组件测试的测试环境。我发现最近很难测试和成功模拟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:xampphtdocsworkspacecoverageproject 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调用的函数执行的覆盖率数据应该没有问题。