TL;DR
PHP5系および7系のassertion失敗時に例外を発生させたい場合はASSERT_CALLBACK
にて自分で記述する。
シチュエーション例
5系および7系をサポートしたいSDKに関して、ユニットテストとは別にシナリオテスト(smoke test)をassertionを使って書いた。
assertion失敗時はtry-catch(-finally)内でcleanup処理をさせたい(ex, DBからテストデータを削除)。
PHPのassert
デフォルトではWarningを発生させるだけで正常終了する。
$php -r 'assert(false, "myTest");'
Warning: assert(): myTest failed in Command line code on line 1
ユニットテストとは別にシナリオテスト(smoke test)をassertionで書いた時、AssertionErrorなど例外終了させたかった。
PHP7系からassert.exception
ディレクティブを設定でき、 このモードはPHP_INI_ALL
なのでphp.iniの他ini_set()
で設定できる。
<?php
ini_set('assert.exception', '1');
assert(false, "myTest"); // Fatal error: Uncaught AssertionError: myTest in /tmp/sample.php:3 + Stack trace(省略)
echo 'not display';
ただし対象のスクリプトは5系サポートもしたい。
5系ではassert.exception
ディレクティブはないため、上記のスクリプトはini_set()
が無視され、assertのWarningとechoが出力されてしまう。
5系および7系で共通して使えるのはassert_options()
というビルトイン関数で、その中に直接的に例外を発生させるオプションは存在しない。
ASSERT_CALLBACK
オプションでassertion失敗時の任意のコールバックを渡せるので、そこで例外発生させる。
<?php
assert_options(ASSERT_CALLBACK, 'assertionError');
function assertionError($script, $line, $message)
{
throw new Exception();
}
try {
assert(false); // Warning: assert(): assert(false) failed in /tmp/sample.php on line 10
echo "not display\n";
} catch(Exception $e) {
echo "cleanup\n"; // cleanup
}
ASSERT_BAIL
というオプションもあるが、これはexit
してしまうのでtry-catchなどで捕捉できない。
ただしASSERT_CALLBACKは呼ばれるので、コールバック内でcleanupする手もあるが、特定のテストデータをクリーンしたい場合は引数が固定のためglobalなどで渡す必要がある。