Я пытаюсь использовать 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);
}
}
или даже это:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
header_remove();
ob_clean();
}
}
вернуть эту ошибку:
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.
Это выглядит так, как будто перед запуском теста на терминал выводится что-то еще, даже если не включен другой файл и нет другого символа перед началом тега PHP. Может быть, что-то внутри PHPunit вызывает это?
В чем может быть проблема?
Ответы:
Проблема в том, что PHPUnit будет печатать заголовок на экране, и в этот момент вы не можете добавить дополнительные заголовки.
Чтобы решить эту проблему, нужно запустить тест в изолированном процессе. Вот пример
<?php class FooTest extends PHPUnit_Framework_TestCase { /** * @runInSeparateProcess */ public function testBar() { header('Location : http://foo.com'); } }
Это приведет к:
$ phpunit FooTest.php PHPUnit 3.6.10 by Sebastian Bergmann. . Time: 1 second, Memory: 9.00Mb OK (1 test, 0 assertions)
Ключ - аннотация @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
Попробуйте добавить это в свой файл начальной загрузки, чтобы исправить это:
<?php if (!defined('PHPUNIT_COMPOSER_INSTALL')) { define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php'); }
источник
PHP Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'SplFileInfo' is not allowed' in phar:///usr/local/bin/phpunit/phpunit/Util/GlobalState.php:211
Хотя запуск теста в отдельном процессе действительно решает проблему, при запуске большого набора тестов возникают заметные накладные расходы.
Мое исправление заключалось в том, чтобы направить вывод phpunit на stderr, например:
Это должно решить проблему, а также означает, что вам не нужно создавать функцию-оболочку и заменять все вхождения в вашем коде.
источник
stderr="true"
в свой phpunit.xml, чтобы сэкономить несколько нажатий клавиш.В стороне: для меня
headers_list()
все время возвращалось 0 элементов. Я заметил комментарий @titel к вопросу и решил, что он заслуживает особого упоминания здесь:HTH
источник
Как уже упоминалось в комментарии, я думаю, что это лучшее решение для определения processIsolation в файле конфигурации XML, например
<?xml version="1.0" encoding="UTF-8"?> <phpunit processIsolation = "true" // ... > </phpunit>
Таким образом, вам не нужно передавать параметр --stderr, который может раздражать ваших коллег.
источник
У меня было более радикальное решение, чтобы использовать его
$_SESSION
внутри моих протестированных / включенных файлов. Я отредактировал один из файлов PHPUnit в ../PHPUnit/Utils/Printer.php, чтобы"session_start();"
перед командой «print $ buffer» был указан .Это сработало для меня как шарм. Но я считаю, что пользовательское решение "joonty" на данный момент является лучшим из всех.
источник
Альтернативным решением для @runInSeparateProcess является указание опции --process -olated при запуске PHPUnit:
name@host [~/test]# phpunit --process-isolation HeadersTest.php
Это аналогично установке параметра processIsolation = "true" в phpunit.xml.
Это решение имеет те же преимущества / недостатки, что и указание опции --stderr, которая, однако, не сработала в моем случае. В принципе, никаких изменений кода не требуется, даже если производительность может снизиться из-за запуска каждого теста в отдельном процессе PHP.
источник
Используйте параметр --stderr для получения заголовков из PHPUnit после ваших тестов.
источник