Saya mencoba menggunakan PHPunit untuk menguji kelas yang menghasilkan beberapa header khusus.
Masalahnya adalah di komputer saya ini:
<?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);
}
}
atau bahkan ini:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
header_remove();
ob_clean();
}
}
kembalikan kesalahan ini:
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.
Ini terlihat seolah-olah ada sesuatu yang lain yang dikeluarkan ke terminal sebelum pengujian dijalankan meskipun tidak ada file lain yang disertakan dan tidak ada karakter lain sebelum permulaan tag PHP. Mungkinkah ada sesuatu di dalam PHPunit yang menyebabkan ini?
Apa masalahnya?
Jawaban:
Masalahnya adalah PHPUnit akan mencetak header ke layar dan pada saat itu Anda tidak dapat menambahkan lebih banyak header.
Solusinya adalah menjalankan pengujian dalam proses yang terisolasi. Berikut ini contohnya
<?php class FooTest extends PHPUnit_Framework_TestCase { /** * @runInSeparateProcess */ public function testBar() { header('Location : http://foo.com'); } }
Ini akan menghasilkan:
$ phpunit FooTest.php PHPUnit 3.6.10 by Sebastian Bergmann. . Time: 1 second, Memory: 9.00Mb OK (1 test, 0 assertions)
Kuncinya adalah anotasi @runInSeparateProcess.
Jika Anda menggunakan PHPUnit ~ 4.1 atau sesuatu dan mendapatkan kesalahan:
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
Coba tambahkan ini ke file bootstrap Anda untuk memperbaikinya:
<?php if (!defined('PHPUNIT_COMPOSER_INSTALL')) { define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php'); }
sumber
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
Meskipun menjalankan pengujian dalam proses terpisah dapat memperbaiki masalah, ada overhead yang terlihat saat menjalankan serangkaian pengujian yang besar.
Perbaikan saya adalah mengarahkan output phpunit ke stderr, seperti:
Itu seharusnya memperbaiki masalah, dan itu juga berarti bahwa Anda tidak perlu membuat fungsi pembungkus dan mengganti semua kejadian dalam kode Anda.
sumber
stderr="true"
phpunit.xml Anda untuk menyimpan beberapa penekanan tombol.Sebagai tambahan: Bagi saya
headers_list()
terus mengembalikan 0 elemen. Saya melihat komentar @titel tentang pertanyaan itu dan menurut saya itu layak untuk disebutkan secara khusus di sini:HTH
sumber
Seperti yang telah disebutkan dalam komentar, saya pikir ini adalah solusi yang lebih baik untuk mendefinisikan processIsolation dalam file konfigurasi XML seperti
<?xml version="1.0" encoding="UTF-8"?> <phpunit processIsolation = "true" // ... > </phpunit>
Seperti ini, Anda tidak harus melewatkan opsi --stderr, yang mungkin mengganggu rekan kerja Anda.
sumber
Saya memiliki solusi yang lebih radikal, untuk digunakan
$_SESSION
di dalam file yang saya uji / disertakan . Saya mengedit salah satu file PHPUnit di ../PHPUnit/Utils/Printer.php agar memiliki"session_start();"
sebelum perintah "print $ buffer" .Ini bekerja untuk saya seperti pesona. Tapi menurut saya solusi pengguna "joonty" adalah yang terbaik hingga saat ini.
sumber
Solusi alternatif untuk @runInSeparateProcess adalah menentukan opsi --process-isolation saat menjalankan PHPUnit:
name@host [~/test]# phpunit --process-isolation HeadersTest.php
Ini serupa dengan menyetel opsi processIsolation = "true" di phpunit.xml.
Solusi ini memiliki kelebihan / kekurangan yang sama dengan menentukan opsi --stderr, yang bagaimanapun tidak berfungsi dalam kasus saya. Pada dasarnya tidak ada perubahan kode yang diperlukan, meskipun mungkin ada kinerja yang terhambat karena menjalankan setiap pengujian dalam proses PHP yang terpisah.
sumber
Gunakan parameter --stderr untuk mendapatkan header dari PHPUnit setelah pengujian Anda.
sumber