Ich versuche, mit PHPunit eine Klasse zu testen, die einige benutzerdefinierte Header ausgibt.
Das Problem ist, dass auf meinem Computer Folgendes:
<?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);
}
}
oder sogar das:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
header_remove();
ob_clean();
}
}
Geben Sie diesen Fehler zurück:
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.
Dies sieht so aus, als würde vor dem Ausführen des Tests etwas anderes auf dem Terminal ausgegeben, obwohl keine andere Datei enthalten ist und vor dem Beginn des PHP-Tags kein anderes Zeichen steht. Könnte es etwas in PHPunit sein, das dies verursacht?
Was könnte das Problem sein?
Antworten:
Das Problem ist, dass PHPUnit einen Header auf dem Bildschirm druckt und Sie zu diesem Zeitpunkt keine weiteren Header hinzufügen können.
Die Problemumgehung besteht darin, den Test in einem isolierten Prozess auszuführen. Hier ist ein Beispiel
Dies führt zu:
Der Schlüssel ist die Annotation @runInSeparateProcess.
Wenn Sie PHPUnit ~ 4.1 oder etwas verwenden und den Fehler erhalten:
Versuchen Sie, dies Ihrer Bootstrap-Datei hinzuzufügen, um das Problem zu beheben:
quelle
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
Obwohl das Ausführen des Tests in einem separaten Prozess das Problem behebt, entsteht beim Ausführen einer großen Testsuite ein spürbarer Overhead.
Mein Fix war, die Ausgabe von phpunit wie folgt an stderr zu leiten:
Dies sollte das Problem beheben und bedeutet auch, dass Sie keine Wrapper-Funktion erstellen und alle Vorkommen in Ihrem Code ersetzen müssen.
quelle
stderr="true"
Ihre phpunit.xml hinzufügen , um einige Tastenanschläge zu speichern.Nebenbei: Für mich wurden
headers_list()
immer wieder 0 Elemente zurückgegeben. Ich habe den Kommentar von @titel zu dieser Frage bemerkt und festgestellt , dass er hier besondere Erwähnung verdient:HTH
quelle
Wie bereits in einem Kommentar erwähnt, ist es meiner Meinung nach eine bessere Lösung, processIsolation in der XML-Konfigurationsdatei wie zu definieren
Auf diese Weise müssen Sie die Option --stderr nicht übergeben, was Ihre Mitarbeiter irritieren könnte.
quelle
Ich hatte eine radikalere Lösung, um sie
$_SESSION
in meinen getesteten / enthaltenen Dateien zu verwenden. Ich habe eine der PHPUnit- Dateien unter ../PHPUnit/Utils/Printer.php bearbeitet , um"session_start();"
vor dem Befehl "print $ buffer" eine zu haben .Es hat bei mir wie ein Zauber funktioniert. Aber ich denke, die "Joonty" -Nutzerlösung ist die bisher beste von allen.
quelle
Eine alternative Lösung zu @runInSeparateProcess besteht darin, die Option --process -isolation anzugeben, wenn PHPUnit ausgeführt wird:
Dies ist analog zum Setzen der Option processIsolation = "true" in phpunit.xml.
Diese Lösung hat ähnliche Vor- und Nachteile wie die Angabe der Option --stderr, die in meinem Fall jedoch nicht funktioniert hat. Grundsätzlich sind keine Codeänderungen erforderlich, auch wenn die Ausführung jedes Tests in einem separaten PHP-Prozess zu Leistungseinbußen führen kann.
quelle
Verwenden Sie den Parameter --stderr, um nach Ihren Tests Header von PHPUnit abzurufen.
quelle