はじめに
単体テスト、機能テストについては、下記を参照してください。
Symfony2 + PHPUnitではじめてのテスト(単体テスト編)
Symfony2 + PHPUnitではじめてのテスト(機能テスト編)
モックを使ってみる
依存しているオブジェクトをシミュレートするのが難しいときに、オブジェクトをモック(代用)に置き換えるのが非常に有効です。
決済モジュールをモックに置き換えてテストします。
決済モジュールをテストする際は、サンドボックス環境を利用するのですが、エラーを細かくシミュレートできないので、エラーの内容ごとに分岐する処理を作る場合に困ってしまいます。
そこでPHPUnitのMockオブジェクトを利用し、期待通りの処理結果(エラーオブジェクト)を返却するようにテストケースを実装します。
実装サンプル
実際、sopra.jpで使っていたコードです。
課金バッチを実行するも、決済エラーになるというシナリオです。
public function testExecute() {
$members = $this->getEntityManager()->getRepository('SopraCoreBundle:Member')->findAll();
foreach ($members as $member) {
$creditCard = new CreditCard('4111111111111111', 2020, 12);
$this->getMembershipManager()->upgrade($member, $creditCard);
}
$cardResponseDto = new CardCaptureResponseDto();
$cardResponseDto->setMstatus('failure');
$cardResponseDto->setVResultCode('NC04000000000000');
$captureResponse = new CaptureResponse($cardResponseDto);
$cardManager = $this->getMock('{Namespace}\Card\CardManager', array('capture'));
$cardManager->expects($this->any())
->method('capture')
->will($this->returnValue($captureResponse));
$captureCommand = new CaptureCommand();
$captureCommand->setCardManager($cardManager);
$application = new Application($this->getKernel());
$application->add($captureCommand);
$command = $application->find('sopra:batch:capture');
$commandTester = new CommandTester($command);
$commandTester->execute(array('command' => $command->getName()));
$dispaly = $commandTester->getDisplay();
echo PHP_EOL.$dispaly;
}
さいごに
自分自身、時間がないことを言い訳に、テストコードを書かずに、これまで過ごしてきましたが、一度はじめてしまうと、癖になりそうな感覚はあります。
テストを書いて良かったなと思うことは、以下のとおりです。
- テストコードを実行してみつかる不具合がある
- テストコードを書いているうちに、実装部分のリファクタリングが進むことがある
- 同じ条件で繰り返しテストを実行できる
- とにかく安心できる
- テストコードはときに取り扱い説明書になる
ただ、小さいチームがはじめてテストコードを書く場合は注意が必要かと思います。(あくまで個人的な意見です)
- はじめること、続けることが大事
- テストを義務にしない
- 自分のために書く
- いきなり大きなテストを書かない
- テストを書きすぎない(実装とのバランスを考える)
- 実環境でのテストが不要になるわけではない
これを機に社内にテストコードを書くエンジニアが増えてきたら、カバレッジ分析、自動テストなどに取り組んでいきたいと思います。