この記事は実用的な目的のみを目的としており、phpunitの概念を理解できるように設計されています。 実装には、ZF、mysql + innodbが使用されますが、必要に応じて、任意のツールキットで使用できます。 さらに、 dklab.ru / lib / PHP_Exceptionizerが使用されます(通知と警告を実行に変換します)。
準備する
テストフォルダは、プロジェクトツリーに次の構造で作成されます。
d-アプリケーション
d-モデル
d-トリガー
...
run.php
アプリケーションおよびモデルフォルダーの内容は、プロジェクト内のコントローラーおよびモデルの構造に従います。 テストスイートは使用しないため、テストを含む新しいファイルをシステムに追加するときに、このテストをスイートに追加する必要はありません。 トリガーフォルダーには、テーブルの名前のフォルダーがあり、その中にはトリガーとして名前が付けられたファイルがあります。
run.phpファイルには、テストの実行に必要なコード(クラスの自動ロード、データベースへの接続など)が含まれています。 スクリプトは、悪意のある環境と戦闘環境の両方で動作するはずです。 これは、Zend_Console_Getoptを使用して実行できます。 行ファイルの最後
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT' );
PHPUnit_TextUI_Command::main();
* This source code was highlighted with Source Code Highlighter .
それらが機能するためには、phpunitをシステムにインストールし、起動用に設定する必要があります。
testsフォルダーからテストを実行するには、次のようにします。
php run.php models / Article(Articleフォルダーのすべてのテストが起動されます)
php run.php models / ArticleTest.php(ArticleTest.phpファイルのすべてのテストが実行されます)
モデルテスト
すべてのテストは、データベースへの接続を含むExt_Db_Table_Test_Abstractクラスから継承されます。 setUpおよびTearDownメソッドはfinalとして宣言され、_startおよび_finishに置き換えられます。 setUpではトランザクションが開始され、tearDownではロールバックされます。 したがって、各テストは独自のトランザクションで実行されるため、オブジェクトを監視してデータベースをクリーンアップする必要がなくなります。
<?
*このソースコードは、 ソースコードハイライターで強調表示されました。
- <?php
- 抽象 クラス Ext_Db_Table_Test_AbstractはPHPUnit_Framework_TestCaseを拡張します
- {
- / **
- * @var Zend_Db_Adapter_Abstract
- * /
- 保護された static $ _db;
- パブリック 静的 関数 setDbAdapter(Zend_Db_Adapter_Abstract $ db = null )
- {
- if (empty($ db)){
- $ db = Zend_Db_Table_Abstract :: getDefaultAdapter();
- }
- self :: $ _ db = $ db;
- }
- / **
- * Zend_Db_Profiler
- *
- * @return Zend_Db_Profiler
- * /
- パブリック 関数 getProfiler()
- {
- return self :: $ _ db-> getProfiler();
- }
- 最終公開 関数 setUp()
- {
- if (empty(self :: $ _ db)){
- self :: setDbAdapter();
- }
- self :: $ _ db-> beginTransaction(); //トランザクション内の各テスト!
- $ this-> _ start();
- }
- 最終公開 関数 tearDown()
- {
- $ this-> _ finish();
- self :: $ _ db-> rollBack();
- }
- 保護された 関数 _start()
- {
- }
- 保護された 関数 _finish()
- {
- }
- }
次の重要なポイントは、フィクスチャの作成です。 テストに関するすべての記事は、このためにPHPUnit拡張機能とそのデータベース拡張機能を使用することを推奨しています。 一般に、これは正しいですが、もっと簡単にしたかったのです。
テストデータを作成するために、シングルトーンとして表示される特別なクラスTest_Objectがあります。
記事が必要な場合は、次のように記述します$ article = Test_Object :: getInstance()-> addArticle();
*このソースコードは、 ソースコードハイライターで強調表示されました。
- パブリック 関数 addArticle(array $ data = array())
- {
- $ base = array(
- 'key' => md5(mt_rand())、
- 'content' => md5(mt_rand())、
- 'name' => md5(mt_rand())、
- 「公開済み」 => 1
- 'file_id' => $ this-> addFile()-> file_id、 //依存オブジェクトを作成します
- 「作成済み」 =>今()
- );
- $ article_table = Article :: getInstance();
- if (empty($ data [ 'article_category_id' ])){ //カテゴリIDを渡さなかった場合、カテゴリは自動的に作成されます
- $ base [ 'article_category_id' ] = $ this-> addArticleCategory($データ)-> article_category_id; // $データ配列は、カテゴリ作成メソッドにも渡されます。
- }
- return $ this-> _ createRow($ article_table、$ base 、$ data);
- }
- 保護された 関数 _createRow(Ext_Db_Table_Abstract $テーブル、配列$ ベース 、配列$データ=配列())
- {
- $ data = array_merge($ base 、$ data);
- $ row = $ table-> createRow($ data);
- $ row-> save();
- $行を返します。
- }
ここで、addArticleに渡すことで必要なデータを簡単に再定義できることがわかります。 また、このメソッドは、それ自体が依存するオブジェクトを作成します($データで渡さない場合)。 現時点では、Test_Objectには、システムで作成されたエンティティが多数あるため、約4,000行のコードが含まれています。 xmlファイルを使用することを想像してください。 このアプローチのもう1つの利点は、オブジェクトの作成が1箇所に集中し、オブジェクトのグラフを簡単に作成できることです。 たとえば、記事へのコメントが必要です;このために、addArticleComment()メソッドが記述され、必要なすべてのaddUser、AddArticleオブジェクトなどが内部的に作成されます。 必要なコメントを返します。
そして今、テスト自体。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- <?php
- ArticleTest クラスは Ext_Db_Table_Test_Abstractを拡張します
- {
- パブリック 関数 testFindByKey()
- {
- $ article = Test_Object :: getInstance()-> addArticle();
- $ row = Article :: getInstance()-> findByKey($ article-> key);
- $ this-> assertEquals($記事、$行);
- }
- }
php run.phpモデルの実行とチェック/ Article / ArticleTest.php
以下は、すべてのモデルテストを実行する例です。 合計で、システムには約1200のテストと約4000のテストがあります(合計カバレッジは90%以上です)。
php run.php model/
PHPUnit 3.3.12 by Sebastian Bergmann.
E........................................................... 60 / 356
............................................................ 120 / 356
............................................................ 180 / 356
F..........................................................I 240 / 356
............................................................ 300 / 356
........................................................
Time: 42 seconds
FAILURES!
Tests: 356, Assertions: 800, Failures: 1, Errors: 1, Incomplete: 1.
コントローラーのテスト
例を使用するとわかりやすくなります。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- <?php
- class Frontend_Tender_EditControllerTest extends ControllerTestCase //環境acl、ルーティングなどが発生するクラス。
- {
- public function testAddAction() //ページが開くことを確認します。
- {
- $ this- > dispatch( '/ tender / add' );
- $ this-> assertNoErrors(); //プラグインエラーがエラーを登録しなかったことを確認します。
- $ this-> assertModuleFromParams( 'tender' );
- $ this-> assertControllerFromParams( 'edit' );
- $ this-> assertActionFromParams( 'add' );
- }
- public function testAddActionWithPost() //フォームを確認します
- {
- $データ=配列(
- 'name' => 'name' 、
- 'content' => md5(mt_rand())、
- 'phone' => '12345' 、
- 'country_id' => 3159、
- 'region_id' => 4312、
- 'city_id' => 4400、
- 「メール」 => md5(mt_rand())。 '@ testemail.ru' 、
- );
- $ this-> getRequest()-> setMethod( 'post' )
- -> setParams($データ);
- $ this- > dispatch( '/ tender / add' );
- $ this-> assertNoErrors();
- $ table = Tender :: getInstance();
- $ row = $ table-> selectByEmail($ data [ 'email' ])-> fetchRow(); //これについては次のトピックで説明します)
- foreach ($キーとしての $データ=> $値){
- $ this-> assertEquals($値、$行-> $キー); //データベースがデータベースにあることを確認します
- }
- }
- }
メソッドassertModuleFromParams、assertControllerFromParams、assertActionFromParamsは$ request-> getParam(blabla)をチェックします。
私たちは積極的にactionStackを使用しており、リクエストを常に変更しているため、$ request-> getModuleName()の確認は実用的ではありません。
おわりに
ここで紹介する方法は、可能な方法の1つにすぎません。 私たちにとって、それは非常に便利なように思え、時の試練をパスしたと言えます。 また、テストを作成していない場合は、テストを開始します。
psハブの最初の投稿 興味深い場合は、私が参加しているプロジェクトのアーキテクチャについて書きます。
pssこの回路はwww.okinfo.ruでテストおよび使用されています