イントロダクション
テストをするというアイディアは決して新しいものではありません。あなたが最後にコミットしたものがアプリケーション全体をダウンさせていないということに確証が持てなければ、きっと夜も心地よく眠ることができないでしょう。しっかりとテストをすることで、あなたのアプリケーションが安定していると確信できるのです。
多くのケースにおいて、テストはあなたのアプリケーションが100%正しく期待通りに動く保証をしているわけではありません。複雑なアプリケーションにおいて、起こりうるすべてのシナリオや例外を事前に把握するのは不可能です。しかしテストをすることにより、あなたのアプリケーションの最も大事な部分は予想通りに、そして確実に動作するという確証を持つことができるのです。
アプリケーションをテストする方法はたくさんあります。 最もポピュラーなパラダイムは 単体テストです。 ウェブアプリケーションでは、コントローラーやモデルを単体でテストしてもあなたのアプリケーションが正しく動作するという保証は持てません。アプリケーション全体の挙動をテストするには、機能テスト(functional test)または受け入れテスト(acceptance test)を書くべきです。
Codeceptionのテストフレームワークはこれらのレベルを区別します。単体テスト、機能テスト、受け入れテストを1つの方法ですぐに書けるようになるためのツールなのです。
それでは、リストされているテストのパラダイムを逆の順序で確認してみましょう。
受け入れテスト
あなたのクライアントやマネージャー、テスターまたは他の技術に詳しくない人はどのようにして、あなたのサイトが動作していることを知ることができますか? ブラウザーを開き、ウェブサイトにアクセスし、リンクをクリックし、フォームを埋め、表示されたウェブページのコンテンツを実際に見る必要があります。その人はウェブサイトがどのようなフレームワークやデータベース、ウェブサーバー、またはプログラミング言語によって実装されているのかを知らないですし、なぜアプリケーションが期待通りに動作しないかも分かりません。
受け入れテストでは、ユーザー視点による標準的かつ複雑なシナリオをカバーすることができます。受け入れテストを行うことで、あなたは定義されたシナリオ通りに動くユーザーがエラーに直面しないと確証を得ることができるのです。
受け入れテストは任意のウェブサイトで行えるということを覚えておいてください。 それは、あなたがカスタマイズしたCMSやフレームワークを使っていたとしてもです。
受け入れテストのサンプル
<?php
$I = new AcceptanceTester($scenario);
$I->amOnPage('/');
$I->click('Sign Up');
$I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']);
$I->see('Thank you for Signing Up!');
長所
- どんなウェブサイト上でも動作します
- javascriptとajaxのリクエストをテストできます
- あなたのクライアントやマネージャーに見せることができます
- 安定的なサポート: ソースコードや技術の変化による影響が小さいです
短所
- 動作が遅い: 動作しているブラウザーとデータベースのデータを入れ直す必要があります
- チェックする項目が少ないと、偽陽性(false-positive)の結果になってしまう可能性があります
- 繰り返しますが、本当に遅いのです
- 実行中の不安定さ: レンダリングやjavascriptの問題は予測できない結果につながる可能性があります
機能テスト
もし私たちのアプリケーションをサーバーを動かさずにチェックできたらどうでしょう?そうすることで私たちは例外の詳細なエラーを見たり、テスト速度を早くしたり、データベースの値が予想通りであることをチェックできるのです。これが機能テストです。
機能テストのためには、ウェブリクエスト($_GET
と$_POST
変数)をエミュレートし、HTMLレスポンスを返すアプリケーションに送信します。テスト内でレスポンスに関するアサーションを行ったり、データがデータベースに正しく格納されたかをチェックすることもできます。
機能テストを行うにあたって、あなたのアプリケーションはテスト環境で実行する準備が整っていなければなりません。。 Codeceptionはいくつかの人気なPHPフレームワークとのコネクターを提供していますが、あなた自身でそれを書くこともできます。
機能テストのサンプル
<?php
$I = new FunctionalTester($scenario);
$I->amOnPage('/');
$I->click('Sign Up');
$I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']);
$I->see('Thank you for Signing Up!');
$I->seeEmailSent('miles@davis.com', 'Thank you for registration');
$I->seeInDatabase('users', ['email' => 'miles@davis.com']);
長所
- 受け入れテストに似ており、より高速です
- より詳細なレポートを提供できます
- このコードをマネージャーやクライアントに見せることも可能です
- 充分な安定: 悪影響を及ぼす可能性があるのは、大規模なコードの変更やフレームワークの変更だけです
短所
- javascriptとajaxをテストできません
- ブラウザーをエミュレートするため、より多くの偽陽性の結果を得るかもしれません
- フレームワークが必要です
単体テスト
複数のコードを連結する前に、コードの断片をテストするのは非常に重要なことです。これを行うことにより、機能テストもしくは受け入れテストでカバーされなかった場合であったとしても、深い箇所に隠されたいくつかの機能がまだ動作するということに確証が得られます。これはまた、あなたが安定したテスト可能なコードを生成したということを証明します。
CodeceptionはPHPUnitの上に作成されています。もしあなたがPHPUnitを使った単体テストを書いた経験があるようでしたら、それを引き続き行うことが可能です。Codeception上で標準のPHPUnitによる単体テストを実行しても問題はありませんが、Codeceptionはあなたの単体テストがより簡単かつ綺麗になるよう構築されたツールをいくつか提供しています。
テストが未経験の開発者でも、何がどのようにテストされているのかを知っておくべきでしょう。要件やコードは急激に変わることがあり、単体テストも要件に合うよう毎回アップデートするべきです。よりベターなのは、あなたがテストのシナリオを理解し、新しい挙動に対して迅速にアップデートすることです。
単体テストのサンプル
<?php
function testSavingUser()
{
$user = new User();
$user->setName('Miles');
$user->setSurname('Davis');
$user->save();
$this->assertEquals('Miles Davis', $user->getFullName());
$this->unitTester->seeInDatabase('users', ['name' => 'Miles', 'surname' => 'Davis']);
}
長所
- 最も早いです(もちろん、現在のサンプルではデータベースのデータを入れ直す必要があります)
- 普段あまり使用されることのない機能もカバーされます
- アプリケーションのコア部分の安定性がテストできます
- 単体テストを書くことで、良い開発者と見なされます :)
短所
- ユニット間の連結についてはテストを行いません
- サポートが不安定: コードの変更に非常に敏感です
まとめ
TDDの幅広い人気にも関わらず、これまでに、すべてのPHP開発者がアプリケーションのための自動化テストを書いてきたわけではありません。Codeceptionのフレームワークはテストを行うのが本当に楽しくなるよう開発されました。それは単体テスト、機能テスト、そして受け入れテストを1つのスタイルで書けるようにしたのです。
これはBDDフレームワークと呼べるでしょう。Codeceptionのすべてのテストは記述作法に基づいて書かれています。テスト本文を見るだけで、あなたは何のテストがどのように行われているのかを明確に理解することができるようになります。多くのアサーションのある複雑なテストでさえ、単純なPHPのDSLで記述されています。