Pertanyaan Uji header PHP dengan PHPUnit


Saya mencoba menggunakan PHPunit untuk menguji kelas yang menghasilkan beberapa header khusus.

Masalahnya adalah pada mesin 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 keluaran ke terminal sebelum tes berjalan meskipun tidak ada file lain yang disertakan dan tidak ada karakter lain sebelum awal tag PHP. Mungkinkah ada sesuatu di dalam PHPunit yang menyebabkan ini?

Apa masalahnya?


75
2018-03-16 22:04


asal


Jawaban:


Masalahnya adalah PHPUnit akan mencetak header ke layar dan pada titik itu Anda tidak dapat menambahkan lebih banyak header.

Pekerjaan sekitar adalah menjalankan tes dalam proses yang terpisah. 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');
}

103
2018-03-17 00:36



Meskipun menjalankan tes dalam proses terpisah tidak memperbaiki masalah, ada overhead yang nyata ketika menjalankan serangkaian tes yang besar.

Perbaikan saya adalah untuk mengarahkan output phpunit ke stderr, seperti:

phpunit --stderr <options>

Itu harus memperbaiki masalah, dan itu juga berarti bahwa Anda tidak perlu membuat fungsi pembungkus dan mengganti semua kemunculan dalam kode Anda.


92
2018-05-30 12:03



Sebagai samping: Bagi saya headers_list() terus mengembalikan 0 elemen. saya perhatikan @titel's komentar pada pertanyaan dan pikir itu pantas disebutkan secara khusus di sini:

Hanya ingin menutupi ini jika ada beberapa orang lain yang tertarik   dalam hal ini juga. headers_list() tidak berfungsi saat menjalankan PHPunit   (yang menggunakan PHP CLI) tetapi xdebug_get_headers() bekerja sebagai gantinya.

HTH


7
2017-10-06 09:29



Saya memiliki solusi yang lebih radikal, untuk digunakan $_SESSION di dalam saya diuji / termasuk file. Saya mengedit salah satu dari itu PHPUnit file di ../PHPUnit/Utils/Printer.php untuk memiliki sebuah "session_start();" sebelum perintah "cetak $ buffer".

Itu berhasil bagi saya seperti pesona. Tapi saya rasa solusi pengguna "joonty" adalah yang terbaik dari semuanya sekarang.


3
2017-11-09 13:12



Solusi alternatif untuk @runInSeparateProcess adalah untuk menentukan opsi --process-isolasi ketika menjalankan PHPUnit:

name@host [~/test]# phpunit --process-isolation HeadersTest.php

Itu analog dengan mengatur opsi processIsolation = "true" di phpunit.xml.

Solusi ini memiliki kelebihan / kekurangan yang sama untuk menentukan opsi --stderr, yang bagaimanapun tidak berfungsi dalam kasus saya. Pada dasarnya tidak diperlukan perubahan kode, meskipun mungkin ada pemukulan kinerja karena menjalankan setiap tes dalam proses PHP terpisah.


0
2018-01-23 17:02



Seperti yang sudah disebutkan dalam komentar, saya pikir itu 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 melewati opsi --stderr, yang mungkin mengganggu rekan kerja Anda.


0
2018-06-12 20:30