petitviolet blog

    PHPのTestでheader関数によるエラーを回避する

    2014-07-17

    QiitaPHP

    まとめ

    header関数を使っている関数などをテストする際には、テストを走らせる前に ob_start()と書きましょう

    問題

    PHP でテストしようとして、何故かSimpleTest - Unit Testing for PHPを利用した

    テストを実行するとheader()によるエラーが出た

    E_WARNING: Cannot modify header information - headers already sent by (output started at ...

    よくある感じのエラーで、header 関数によって header を設定しているが、その前にすでにechoprint_rなどで標準出力されている場合に出力されるエラーです テストモジュール自体が標準出力しているために、テストしたい場所でheader()を読んでも時既に遅し、的な感じ

    なお、SimpleTest 以外で同様のエラーが出るかどうかは知らない

    エラーの出るテストコード例

    test.php
    <?php
    mb_internal_encoding('UTF-8');
    
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');
    
    class TestParameter extends UnitTestCase {
      public function __construct() {
      }
    
      public function testVar() {
        header("Content-Type: text/xml; charset=utf-8");
        $this->assertEqual("1", "1");
      }
    }
    $test = new TestParameter();
    $test -> run(new TextReporter());
    
    ?>
    

    これを走らすと...

    $ php test.php
    TestParameter
    E_WARNING: Cannot modify header information - headers already sent by (output started at {PATH}/simpletest/repoter.php) in {PATH}/test.php on line 12
    Exception 1!
    Unexpected PHP error [Cannot modify header information - headers already sent by (output started at {PATH}/simpletest/reporter.php:213)] severity [2] in [{PATH}/test.php line 12]
            in testVar
    FAILURES!!!
    Test cases run: 1/1, Passes: 1, Failures: 0, Exceptions: 1
    

    というエラーが出てしまう

    エラーの出ないテストコード例

    まとめにも書いたように、テストの前にob_start()と書けばよい

    test.php
    <?php
    mb_internal_encoding('UTF-8');
    
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');
    
    class TestParameter extends UnitTestCase {
      public function __construct() {
      }
    
      public function testVar() {
        header("Content-Type: text/xml; charset=utf-8");
        $this->assertEqual("1", "1");
      }
    }
    ob_start();  // これ
    $test = new TestParameter();
    $test -> run(new TextReporter());
    
    ?>
    

    これで

    $ php test.php
    TestParameter
    OK
    Test cases run: 1/1, Passes: 1, Failures: 0, Exceptions: 0
    

    となって一安心

    ob_start()は標準出力自体を取得するための準備であるため、これを呼んでおくと標準出力が内部のバッファに保存されて、header()と干渉しなくなったと思われる

    from: https://qiita.com/petitviolet/items/96e64f709f0ef7dcf612