使用PHPUnit测试PHP头文件

tit*_*tel 87 php phpunit unit-testing output-buffering

我正在尝试使用PHPunit来测试输出一些自定义标头的类.

问题是在我的机器上这个:

<?php

class HeadersTest extends PHPUnit_Framework_TestCase {

    public function testHeaders()
    {
        ob_start();

        header('Location: foo');
        $headers_list = headers_list();
        header_remove();

        ob_clean();

        $this->assertContains('Location: foo', $headers_list);
    }
}
Run Code Online (Sandbox Code Playgroud)

甚至这个:

<?php

class HeadersTest extends PHPUnit_Framework_TestCase {

    public function testHeaders()
    {
        ob_start();

        header('Location: foo');
        header_remove();

        ob_clean();
    }
}
Run Code Online (Sandbox Code Playgroud)

返回此错误:

name@host [~/test]# phpunit --verbose HeadersTest.php 
PHPUnit 3.6.10 by Sebastian Bergmann.

E

Time: 0 seconds, Memory: 2.25Mb

There was 1 error:

1) HeadersTest::testHeaders
Cannot modify header information - headers already sent by (output started at /usr/local/lib/php/PHPUnit/Util/Printer.php:173)

/test/HeadersTest.php:9

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
Run Code Online (Sandbox Code Playgroud)

这看起来好像在测试运行之前还有其他东西输出到终端,即使没有包含其他文件且在PHP标记开头之前没有其他字符.它可能是PHPunit中导致这种情况的东西吗?

问题可能是什么?

Sam*_*ssy 114

问题是PHPUnit会在屏幕上打印标题,此时您无法添加更多标题.

解决方法是在一个独立的过程中运行测试.这是一个例子

<?php

class FooTest extends PHPUnit_Framework_TestCase
{
    /**
     * @runInSeparateProcess
     */
    public function testBar()
    {
        header('Location : http://foo.com');
    }
}
Run Code Online (Sandbox Code Playgroud)

这将导致:

$ phpunit FooTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.

.

Time: 1 second, Memory: 9.00Mb

OK (1 test, 0 assertions)
Run Code Online (Sandbox Code Playgroud)

关键是@runInSeparateProcess注释.

如果您使用PHPUnit~4.1或其他东西并得到错误:

PHP Fatal error:  Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in -:378
Stack trace:
#0 {main}
  thrown in - on line 378

Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378

Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378

Call Stack:
    0.0013     582512   1. {main}() -:0
Run Code Online (Sandbox Code Playgroud)

尝试将此添加到您的引导程序文件以修复它:

<?php
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
    define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php');
}
Run Code Online (Sandbox Code Playgroud)

  • 这会导致错误,有一些define()语句PHPUnit_Framework_Exception:注意:已经定义了常量xyz (7认同)
  • 应用时我得到了这个:`PHP致命错误:在phar:///usr/local/bin/phpunit/phpunit/Util/GlobalState.php中,不允许使用'序列化'SplFileInfo'消息的未捕获异常'异常': 211` (4认同)
  • 这绝对是解决问题的最佳选择.它就像一个魅力! (2认同)
  • 我不得不使用xdebug_get_headers()来获取set头数组.headers_list()全局函数在我的情况下不起作用. (2认同)

Jon*_*rns 101

尽管在单独的进程中运行测试确实解决了问题,但在运行大量测试时会出现明显的开销.

我的修复是将phpunit的输出定向到stderr,如下所示:

phpunit --stderr <options>
Run Code Online (Sandbox Code Playgroud)

这应该可以解决问题,这也意味着您不必创建包装函数并替换代码中的所有实例.

  • 你可以在你的phpunit.xml中添加`stderr ="true"`来保存一些键击. (38认同)
  • 辉煌!没有更改我的代码,没有单独的进程,它的工作原理. (3认同)

Mel*_*lle 8

暂且不说:对我来说,headers_list()不断回归0元素.我注意到@titel对这个问题的评论,并认为值得特别提及:

如果还有其他人对此感兴趣,我只想介绍一下.headers_list()运行PHPunit(使用PHP CLI)时不起作用,但xdebug_get_headers()工作正常.

HTH


Pep*_*gel 5

正如评论中已经提到的,我认为在 XML 配置文件中定义 processIsolation 是一个更好的解决方案,例如

     <?xml version="1.0" encoding="UTF-8"?>
     <phpunit
        processIsolation            = "true"
        // ... 
     >
     </phpunit>
Run Code Online (Sandbox Code Playgroud)

像这样,您不必传递 --stderr 选项,这可能会激怒您的同事。

  • 最好只为需要它的测试定义它。为所有测试设置它只会使运行测试变慢。 (4认同)