web-dev-qa-db-ja.com

PHP単体テストの実行中にCLIで出力する方法は?

PHPUnitテストを実行するとき、1つまたは2つのことをデバッグできるように、出力をダンプできるようにします。

私は次のことを試しました( PHPUnit Manualの例 と同様);

class theTest extends PHPUnit_Framework_TestCase
{
    /**
     * @outputBuffering disabled
     */
    public function testOutput() {
        print_r("Hello World");
        print "Ping";
        echo "Pong";
        $out = "Foo";
        var_dump($out);
    }   
}

次の結果:

PHPUnit @package_version@ by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.00Mb

OK (1 test, 0 assertions)

予想される出力がないことに注意してください。

HEADバージョンの git repos を2011年9月19日現在使用しています。

php -versionの出力:

$ php -version
PHP 5.2.9 (cli) (built: Dec  8 2010 11:36:37) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans

私が間違っていることはありますか、これは潜在的にPHPUnitのバグですか?

125
Jess Telford

UPDATE

--verboseコマンドラインオプションよりもはるかに優れた動作をする別の方法を実現しました。

class TestSomething extends PHPUnit_Framework_TestCase {
    function testSomething() {
        $myDebugVar = array(1, 2, 3);
        fwrite(STDERR, print_r($myDebugVar, TRUE));
    }
}

これにより、--verbose CLIオプションに付随するすべての不要な出力なしで、いつでもコンソールに何かをダンプできます。


他の回答が指摘しているように、次のような組み込みメソッドを使用して出力をテストすることが最善です。

$this->expectOutputString('foo');

ただし、いたずらになり、テストケース内から1回限りの一時的なデバッグ出力を確認すると役立つ場合があります。ただし、var_dumpハック/回避策は必要ありません。これは、テストスイートの実行時に--verboseコマンドラインオプションを設定することで簡単に実現できます。例えば:

$ phpunit --verbose -c phpunit.xml

これにより、CLI環境で実行中のテストメソッド内からの出力が表示されます。

参照: PHPUnitのテストの作成-出力のテスト

158
rdlowrey

更新:はるかに簡単な回避策としてのfwrite(STDERR, print_r($myDebugVar, TRUE));の使用に関しては rdlowreyの以下の更新 を参照


この動作は意図的なものです( jasonbar には 指摘 があります)。マニュアルの矛盾する状態は、PHPUnitに対して reported です。

回避策は、予想される出力が空であることをPHPUnitにアサートさせることです(実際には出力がある場合)。これにより、予期しない出力が表示されます。

class theTest extends PHPUnit_Framework_TestCase
{
    /**
     * @outputBuffering disabled
     */
    public function testOutput() {
        $this->expectOutputString(''); // tell PHPUnit to expect '' as output
        print_r("Hello World");
        print "Ping";
        echo "Pong";
        $out = "Foo";
        var_dump($out);
    }   
}

与える:

PHPUnit @package_version@ by Sebastian Bergmann.

F

Time: 1 second, Memory: 3.50Mb

There was 1 failure:

1) theTest::testOutput
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-''
+'Hello WorldPingPongstring(4) "Foo"
+'

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

出力アサーションがテストされる前に失敗する可能性があるため、テスト用の他のアサーションを必ず無効にしてください(したがって、出力が表示されません)。

32
Jess Telford

--debugを使用してみてください

インクルードまたはソースデータファイルへの正しいパスを取得しようとしている場合に便利です。

27
chim

これはバグではありませんが、非常に意図的なものです。最善の策は、何らかの種類のログファイルに書き込み、ログをテールして出力を監視することです。

出力をテストしようとしている場合は、 this outを確認してください。

また:

:PHPUnitは、テストの実行中に出力されるすべての出力を飲み込むことに注意してください。厳格モードでは、出力を出すテストは失敗します。

9
jasonbar

私は VisualPHPUnit でいくらか運があり、とりわけ出力を表示します。

class TestHello extends PHPUnit_Framework_TestCase 
{
    public function test_Hello() 
    {
        print "hello world";
    }
}

TestHello results

7
Bob Stein

本当にあなたの意図を考えるべきです:テストを修正するためにデバッグするときに今すぐ情報が必要なら、テストが壊れたときに来週再びそれが必要になります。

これは、テストが失敗したときの情報alwaysが必要であることを意味します。また、var_dumpを追加して原因を特定するのは大変な作業です。むしろ、データをアサーションに入れてください。

コードが複雑すぎる場合は、1つのアサーション(カスタムメッセージを含む)でコードの破損箇所、理由、および修正方法を知るのに十分なレベルに達するまで、コードを分割します。

5
cweiske

Hackish、but works:デバッグ出力をメッセージとして例外をスローします。

class theTest extends PHPUnit_Framework_TestCase
{
    public function testOutput() {
        throw new \Exception("hello");
    }   
}

利回り:

...
There was 1 error:

1) theTest::testOutput
Exception: hello
3
Matthias Rella

laravel 5では、dump()を使用できます。最後の応答からコンテンツをダンプします。

class ExampleTest extends TestCase{
    public function test1()
    {
        $this->post('/user', ['name' => 'Gema']);
        $this->dump();
    }
}

与える

3
Branny Bk

場合によっては、そのようなものを使用してコンソールに何かを出力できます

class yourTests extends PHPUnit_Framework_TestCase
{
    /* Add Warnings */
    protected function addWarning($msg, Exception $previous = null)
    {
        $add_warning = $this->getTestResultObject();
        $msg = new PHPUnit_Framework_Warning($msg, 0, $previous);
        $add_warning->addWarning($this, $msg, time());
        $this->setTestResultObject($add_warning);
    }

    /* Add errors */
    protected function addError($msg, Exception $previous = null)
    {
        $add_error = $this->getTestResultObject();
        $msg = new PHPUnit_Framework_AssertionFailedError($msg, 0, $previous);
        $add_error->addError($this, $msg, time());
        $this->setTestResultObject($add_error);
    }

    /* Add failures */
    protected function addFailure($msg, Exception $previous = null)
    {
        $add_failure = $this->getTestResultObject();
        $msg = new PHPUnit_Framework_AssertionFailedError($msg, 0, $previous);
        $add_failure->addFailure($this, $msg, time());
        $this->setTestResultObject($add_failure);
    }

    public function test_messages()
    {
        $this->addWarning("Your warning message!");
        $this->addError("Your error message!");
        $this->addFailure("Your Failure message");
    }

    /* Or just mark test states! */
    public function test_testMarking()
    {
        $this->markTestIncomplete();
        $this->markTestSkipped();
    }
}
3
mkungla

実行時に-verboseフラグを使用するだけですphpunit

$ phpunit --verbose -c phpunit.xml 

この方法の利点は、テストコードを変更する必要がなく、文字列、var_dumpをいつでも印刷できること、およびverboseモードが設定されている場合にのみコンソールに表示されることです。 。

これがお役に立てば幸いです。

2
Fabricio

これは フィクスチャに関するPHPUnit Docs から取られました。

これにより、phpunitテストのライフサイクル中の任意の時点で情報をダンプできます。

次のコードの__METHOD__を出力したいものに置き換えてください

例4.2:利用可能なすべてのテンプレートメソッドを示す例

<?php
class TemplateMethodsTest extends PHPUnit_Framework_TestCase
{
    public static function setUpBeforeClass()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function setUp()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function assertPreConditions()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    public function testOne()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        $this->assertTrue(TRUE);
    }

    public function testTwo()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        $this->assertTrue(FALSE);
    }

    protected function assertPostConditions()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function tearDown()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    public static function tearDownAfterClass()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function onNotSuccessfulTest(Exception $e)
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        throw $e;
    }
}
?>
2
Chris

HTMLベースのTestresultsを出力しました。この場合、コンテンツをフラッシュすると役に立ちました。

var_dump($array);
ob_flush();

2番目のPHPメソッドがあります

flush() 

私は試していません。

1
Sudo

このコードが機能するためには ソースコードの変更 が必要だったので、 this forked repos のURLをcomposerに追加する必要があります

class TestCase extends \PHPUnit_Framework_TestCase
{
    /**
     *  Save last response
     * @var Response|null A Response instance
     */
    static $lastResponse;
    /**
     *  Modify to save response
     *
     * @param  string $method
     * @param  string $uri
     * @param  array $parameters
     * @param  array $files
     * @param  array $server
     * @param  string $content
     * @param  bool $changeHistory
     * @return \Illuminate\Http\Response
     */
    final public function call(
        $method,
        $uri,
        $parameters = [],
        $files = [],
        $server = [],
        $content = null,
        $changeHistory = true
    ) {

        $response = parent::call($method, $uri, $parameters, $files, $server, $content, $changeHistory);
        static::$lastResponse = $this->client->getResponse();
        return $response;
    }


    /**
     * Modify message to add response text
     *
     * @param mixed $value
     * @param PHPUnit_Framework_Constraint $constraint
     * @param string $message
     * @since  Method available since Release 3.0.0
     */
    final public static function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')
    {
        $message .= PHP_EOL . static::$lastResponse . PHP_EOL;
        parent::assertThat($value, $constraint, $message);
    }
}
0
gadelkareem

PHPUnit 4.xでデバッグメッセージを印刷するのに便利なメソッドは次のとおりです。

  • syslog(LOG_DEBUG, "Debug: Message 1!");

    より実用的な例:

    syslog(LOG_DEBUG, sprintf("%s: Value: %s", __METHOD__, var_export($_GET, TRUE)));
    

    syslog() を呼び出すと、システムログメッセージが生成されます(man syslog.confを参照)。

    注:可能なレベル:LOG_DEBUGLOG_INFOLOG_NOTICELOG_WARNINGLOG_ERRなど.

    MacOSで、syslogメッセージをリアルタイムでストリーミングするには、次を実行します。

    log stream --level debug --predicate 'processImagePath contains "php"'
    
  • fwrite(STDERR, "LOG: Message 2!\n");

    注:stdinからPHPスクリプトを読み取る場合、STDERR定数は使用できません。これが の回避策です

    注:STDERRの代わりに、ファイル名も指定できます。

  • file_put_contents('php://stderr', "LOG: Message 3!\n", FILE_APPEND);

    注: STDERR constant が定義されていない場合、このメソッドを使用します。

  • register_shutdown_function('file_put_contents', 'php://stderr', "LOG: Message 4!\n", FILE_APPEND);

    注:テストに影響を与えずに最後に何かを印刷する場合は、この方法を使用します。

変数をダンプするには、var_export()を使用します。 "Value: " . var_export($some_var, TRUE) . "\n"

上記のメッセージを冗長モードまたはデバッグモードでのみ出力するには、以下を参照してください: テストで--debugまたは--verboseがPHPUnitに渡されたかどうかを確認する方法はありますか?


出力のテストがテスト自体の一部である場合は、チェックアウト: Testing Output docs page。

0
kenorb