BIOGRAPHYREADME2017.06.19PHPUnitで例外を投げた後の処理をテストする例えばこんなクラスコードがあるとする。}}ブログを投稿する簡単なクラス。INSERT文を2つ発行するのでトランザクションを貼って、もしデータベース例外が発生したらloggingした上で例外を投げ直すというよくあるコード。これに対してテストコードをPHPUnitで書いてみる。テスト方針スタンダードに以下のようなテストケースを書いてみる。IDを返すINSERTがどちらかコケたらログを取った上で例外を投げる上記のクラスはきれいにDIパターンで実装されているのでいずれのテストもモックを注入し、振る舞いを指定することでロジックの保証をするテストが書ける。後者のテストを実装するならこんな感じ。}}色々はしょってるけどだいたいこんな感じになると思う。現実のサービスはこんな単純な仕様であることはほぼない。ここに追加仕様で「例外を投げたらloggingし、rollbackし、エラーをテキストファイルに吐き出すようにする」みたいなものが来たとする。(いい例えが思いつかなかっただけで、現実的にはもっと別のケースがあるでしょう)こんなコード。}これに対して先程のテストコードだと「エラーをテキストファイルに吐き出す」ことの確認ができない。ファイル書き込みロジックは外部注入していないのでモックすることもできない。そこでこんなテストを書いてみるとする。}}例外を投げられた後だとプログラムが続行できないので例外をcatchしてassertionする。例外をcatchできなかったらテストをコケるようにして例外を投げることを保証する。これで一件落着、と思いきやこの書き方には2つ問題がある。テストの書き方によってはスタックトレースが表示されず何がなんだか分からないテストの中にロジックが混ざって可読性が下がる前者に関しては以下のようなテストの書き方をしてると起きる。return;}こんな書き方しなきゃいいじゃんって話なんだけど、時たまやるしテストやロジックが複雑化していけばなおさら起きる。いえこういうことは往々にして起きるのでもう少し違うアプローチを考えることにした。テストを分けるシンプルにテストを分けてコケたときのエラートラッキングを分けるようにする。具体的には「意図した例外が投げられること」と「例外が投げられた後の状態が望みどおりであること」の2ケースに分ける。イメージ的にはこんな感じ。}}こうすることで意図しない例外が発生しても原因の切り分けが多少やりやすくなる。改善する点としてこの2ケースは前者がコケた時点で後者をテストする必要がない。そこで@dependsアノテーションを利用して前者がコケたら後者がコケるようにする。}}これで完璧!!テストを書くのは楽しいね。