Как получить покрытие php-кода для запуска тестовых случаев phpt? - PullRequest
4 голосов
/ 11 апреля 2011

У меня есть тестовая среда, в которой выполняются тесты компонентов для продукта.Я обнаружил, что в последнее время было сложно тестировать и успешно имитировать 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%

Ответы [ 2 ]

1 голос
/ 10 ноября 2014

Поскольку PhpUnit имеет собственную реализацию для запуска файлов PHPT, которая происходит в отдельном процессе, получение покрытия кода , интегрированного с PhpUnit, может оказаться довольно сложным.

Однако, если всепотребность в покрытии (или вы готовы сделать некоторую постобработку самостоятельно) становится довольно тривиальной.

В самой простой форме все, что вам нужно сделать, это сделать вызовы xDebug из ваших файлов PHPT.Используя 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файл вы можете легко получить доступ к файлам конфигурации или добавить другую логику.

0 голосов
/ 16 апреля 2011

Я не знаю точно, почему PHPUnit не будет собирать эти данные покрытия для вас. Это может быть связано с тем, как он использует (или не использует) XDebug.

Вы можете обойти это, используя инструмент тестирования покрытия, который не зависит от работы PHPUNit или XDebug.

Наше Покрытие теста PHP будет собирать покрытие теста для любой функции в любом PHP-скрипте, который было задано отслеживать, независимо от того, как эта функция выполняется. Он не должен иметь проблем с предоставлением данных о выполнении функций, вызванных PHPT.

...