Próbuję użyć PHPunit do przetestowania klasy, która wyprowadza niektóre niestandardowe nagłówki.
Problem w tym, że na moim komputerze to:
<?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);
}
}
a nawet to:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
header_remove();
ob_clean();
}
}
zwróć ten błąd:
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.
Wygląda na to, że przed uruchomieniem testu do terminala jest wysyłane coś innego, mimo że nie ma dołączonego innego pliku i nie ma innego znaku przed początkiem znacznika PHP. Czy przyczyną tego może być coś wewnątrz PHPunit?
Jaki może być problem?
Odpowiedzi:
Problem polega na tym, że PHPUnit wydrukuje nagłówek na ekranie iw tym momencie nie możesz dodać więcej nagłówków.
Rozwiązaniem jest uruchomienie testu w izolowanym procesie. Oto przykład
<?php class FooTest extends PHPUnit_Framework_TestCase { /** * @runInSeparateProcess */ public function testBar() { header('Location : http://foo.com'); } }
Spowoduje to:
$ phpunit FooTest.php PHPUnit 3.6.10 by Sebastian Bergmann. . Time: 1 second, Memory: 9.00Mb OK (1 test, 0 assertions)
Kluczem jest adnotacja @runInSeparateProcess.
Jeśli używasz PHPUnit ~ 4.1 lub czegoś podobnego i otrzymujesz błąd:
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
Spróbuj dodać to do pliku bootstrap, aby to naprawić:
<?php if (!defined('PHPUNIT_COMPOSER_INSTALL')) { define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php'); }
źródło
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
Chociaż uruchomienie testu w oddzielnym procesie rozwiązuje problem, podczas uruchamiania dużego zestawu testów występuje zauważalny narzut.
Moją poprawką było skierowanie wyjścia phpunita na stderr, na przykład:
To powinno rozwiązać problem, a także oznacza, że nie musisz tworzyć funkcji opakowującej i zastępować wszystkich wystąpień w kodzie.
źródło
stderr="true"
plik phpunit.xml, aby zaoszczędzić kilka naciśnięć klawiszy.Na marginesie: dla mnie
headers_list()
zwracało 0 elementów. Zauważyłem komentarz @titel do pytania i doszedłem do wniosku, że zasługuje na specjalną wzmiankę:HTH
źródło
Jak już wspomniano w komentarzu, myślę, że lepszym rozwiązaniem jest zdefiniowanie processIsolation w pliku konfiguracyjnym XML, np
<?xml version="1.0" encoding="UTF-8"?> <phpunit processIsolation = "true" // ... > </phpunit>
W ten sposób nie musisz przechodzić opcji --stderr, która może irytować twoich współpracowników.
źródło
Miałem bardziej radykalne rozwiązanie, aby używać
$_SESSION
wewnątrz moich testowanych / dołączonych plików. Edytowałem jeden z plików PHPUnit pod adresem ../PHPUnit/Utils/Printer.php, aby"session_start();"
przed poleceniem „print $ buffer” znajdował się znak „print $ buffer” .U mnie zadziałało jak urok. Ale myślę, że rozwiązanie użytkownika "joonty" jest najlepsze z dotychczasowych.
źródło
Alternatywnym rozwiązaniem dla @runInSeparateProcess jest określenie opcji --process-isolation podczas uruchamiania PHPUnit:
name@host [~/test]# phpunit --process-isolation HeadersTest.php
Jest to analogiczne do ustawienia opcji processIsolation = "true" w phpunit.xml.
To rozwiązanie ma podobne zalety / wady jak podanie opcji --stderr, która jednak nie zadziałała w moim przypadku. Zasadniczo nie są konieczne żadne zmiany kodu, nawet jeśli może wystąpić spadek wydajności z powodu uruchamiania każdego testu w oddzielnym procesie PHP.
źródło
Użyj parametru --stderr, aby pobrać nagłówki z PHPUnit po przeprowadzeniu testów.
źródło