LoginSignup
6
1

More than 3 years have passed since last update.

PHPUnit でエラー時に任意のメッセージをテスト結果に表示させる

Last updated at Posted at 2019-03-28

PHPUnit でテストが失敗した時に任意のメッセージを表示させたい。あと fail() メソッドで強制的に失敗させた場合など。

しかも php.iniphpunit.xml をいじらず、手軽に。

phpunit エラー時 メッセージ 任意 表示」で Qiita 記事に絞ってググってみたのですが、タイトルからピンポイントでわかる記事がなかったので、自分のググラビリティとして。

TL; DR

すべてのアサーションの最後の引数は、エラー時のメッセージが指定できるようになっています。

assertTrue()の場合の例
assertTrue(bool $condition[, string $message = ''])
class SampleTest extends TestCase
{
    public function testForceFail()
    {
        $result = false;
        $message = '失敗しちゃった。てへ';
        $this->assertTrue($result, $message);
    }
}

アサーションではありませんが、わざと失敗にする、つまり強制的にエラーにする fail() メソッドにもメッセージが指定できます。

fail()メソッド
fail([string $message = ''])
class SampleTest extends TestCase
{
    public function testForceFail()
    {
        if (true) {
            $this->fail('失敗しちゃった。てへ');
        }
    }
}

TS; DR

PHP に限らず、Bash、 Python、 Docker などでコツコツと作った「俺様スクリプト集」があります。いずれも shebang 付きなので、ファイル名を指定するだけで単体コマンドとして動作します。

イメージとしてはこんな感じのコマンド(スクリプト)です。正常終了時は、実行ステータスを "0"、失敗した場合は実行ステータス "1" で終了します。

コマンドの動作例(実装言語は謎)
$ /Regulation/REG-000 'Hello World!'
$ echo $?
0
$ /Regulation/REG-000 'Hell World!'
NG (Bad argument. Must be 'Hello World!'. Given: Hell World!)
$ echo $?
1

こういった、コマンドの動作テストには Bash の Unit Test で有名な batsBash Automated Testing System)を使うのが一般的だと思います。

しかし、なぜか PHPUnit を使いたかったのです。しかも、久しぶりの PHP と PHPUnit だったので色々と忘れてました。

ググってみたのですが、タイトルからピンポイントの記事がありません。それっぽい記事を開いても、「"phpunit.xml" に display_errorsdisplay_startup_errors を入れろ」とあったり、「"php.ini" をいじれ」といった記事が大半でした。

PHP のシンタックス・エラーとかでなく、普通にテスト失敗時にオリジナル(任意)のコメントを表示させたいだけなのです。

「エラー時にメッセージを表示させるだけに、そこまでせんといかんのか」と PHPUnit を使うのを諦めそうになったところ、普通に PHPUnit 公式のドキュメントに記載がありました。そして普通に引数に渡せばよかったのでした・・・

assertTrue()

assertTrue(bool $condition[, string $message = ''])

$conditionfalse の場合にエラー $message を報告します。

実際には、PHPUnit のDocker のコンテナにマウントしていますが、ローカルでもこんな感じです。

ディレクトリ構成
$ tree /Regulation
.
├── REG-000
├── REG-001
├── REG-002
├── REG-003
├── tests
│   ├── REG-000_Test.php
│   ├── REG-001_Test.php
│   ├── REG-002_Test.php
│   ├── REG-003_Test.php
│   ├── autoload.php
│   └── phpunit.xml
└── run_tests.sh
REG-000コマンドの動作例(実装言語は謎)
$ /Regulation/REG-000 'Hello World!'
$ echo $?
0
$ /Regulation/REG-000 'Hell World!'
NG (Bad argument. Must be 'Hello World!'. Given: Hell World!)
$ echo $?
1
run_tests.sh
#!/usr/bin/env bash

phpunit --configuration /Regulation/tests/phpunit.xml /Regulation/tests
REG-000_Test.php(わざとテストを失敗させて動作確認)
<?php
namespace REG\Tests;

class Reg000Test extends TestCase
{
    public function testReg000()
    {
        $message  = 'Hell World!';
        $lastline = exec("/Regulation/REG-000 '${message}'", $output, $return_var);
        $this->assertTrue($return_var === 0, $lastline);
    }
}
phpunit.xml
<?xml version="1.0" encoding="UTF-8" ?>
<phpunit bootstrap="autoload.php">
    <testsuites>
        <testsuite name="Test suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>
autoload.php
<?php
namespace REG\Tests;

// これは Docker phpunit/phpunit の場合の autoload 先ですが、
// 適宜自分の composer の autoload.php のパスを指定してください。
require_once('/tmp/vendor/autoload.php');

class TestCase extends \PHPUnit\Framework\TestCase
{
    // Warning も確実にエラーとして扱うようにする
    public function setUp()
    {
        set_error_handler(function ($errno, $errstr, $errfile, $errline) {
            $msg  = 'Error #' . $errno . ': ';
            $msg .= $errstr . " on line " . $errline . " in file " . $errfile;
            throw new RuntimeException($msg);
        });
    }
    public function tearDown()
    {
        restore_error_handler();
    }
}
テストの実行例(わざとテストを失敗させて、メッセージを確認)
$ # テスト実行
$ cd /Regulation
$ ./run_tests.sh
PHPUnit 6.5.13 by Sebastian Bergmann, Julien Breux (Docker) and contributors.

F                                                                   1 / 1 (100%)

Time: 250 ms, Memory: 4.00MB

There was 1 failure:

1) REG\Tests\Reg000Test::test_Reg000
NG (Bad argument. Must be 'Hello World!'. Given: Hell World!)
Failed asserting that false is true.

/Regulation/tests/REG-000_Test.php:13

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
$ 
$ echo $?
1

一応、正しいテストも。

REG-000_Test.php(今後は正しいテスト)
<?php
namespace REG\Tests;

class Reg001Test extends TestCase
{
    public function testReg000()
    {
        // 正しいデータでのテスト
        $message  = 'Hello World!';
        $lastline = exec("/Regulation/REG-000 '${message}'", $output, $return_var);
        $this->assertTrue($return_var === 0, $lastline);

        // 間違ったデータでのテスト
        $message  = 'Hell World!';
        $lastline = exec("/Regulation/REG-000 '${message}'", $output, $return_var);
        $this->assertTrue($return_var === 1, $lastline);
    }
}
テストの実行(今度はパス)
$ cd /Regulation
$ ./run_tests.sh
PHPUnit 6.5.13 by Sebastian Bergmann, Julien Breux (Docker) and contributors.

.                                                                   1 / 1 (100%)

Time: 215 ms, Memory: 4.00MB

OK (1 test, 2 assertions)
$ 
$ echo $?
0
動作確認済み環境情報
$ # OS(macOS Mojave)
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.4
BuildVersion:   18E226

$ # PHP バージョン
$ php -v
PHP 7.1.23 (cli) (built: Feb 22 2019 22:08:13) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

$ # PHPUnit バージョン
$ phpunit --version
PHPUnit 6.5.13 by Sebastian Bergmann, Julien Breux (Docker) and contributors.

$ # Composer バージョン
$ composer --version
Composer version 1.7.2 2018-08-16 16:57:12
6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1