CodeIgniter 3.0でPHPUnitを使う
CodeIgniter 2.xの時代にはCIUnitというツールを使い、CodeIgniterでPHPUnitによるテストを書いていました。
CodeIgniter 3.0時代になり状況がどう変わったかというと、CodeIgniter本体のテストは進んだようですが、アプリケーションのテストをどうするかという問題は公式にはとくに変化はないようです。
そして、実際にどのようにしているかについては、割と混沌としていました。
- fmalk/codeigniter-phpunit ... 一番人気?
- Celc/CIUnit ... my-ciunitのfork。3.0未対応?
- RodolfoSilva/CIUnit-for-CI3 ... CIUnit-for-CI2のfork
- NEKOGET/CIUnit-for-CI3 ... CIUnit-for-CI2のfork
- PHPUnit and CodeIgniter 3.0 | SpiderSoft
以上のような方法・ツールがあるようです。
個人的にできるだけCodeIgniter本体に手を入れずにPHPUnitを使いたいと考えていましたが、これだというものはありませんでした。
ci-phpunit-test
そこで「ci-phpunit-test」というツールを作成しました。
インストール方法
ダウンロード
(2015-06-12 更新)
GitHubから最新版(https://github.com/kenjis/ci-phpunit-test/releases)をダウンロードして展開します。
以下のようなフォルダ構成になっています。このapplication/tests
フォルダを自分のCodeIgniterプロジェクトのapplication/tests
としてコピーします。
ci-phpunit-test/
├── application/
│ ├── database/
│ ├── helpers/
│ ├── libraries/
│ └── tests/
├── bin/
└── docs/
application
フォルダのその他のファイルはサンプルです。必要に応じてCodeIgniterプロジェクトにコピーしてください(後述)。
パスの調整
(2015-06-15 追記) この手順はci-phpunit-test v0.1.1以降不要になりました。
ci-phpunit-testはデフォルトでは、CodeIgniter Composer Installerによる以下のフォルダ構成を前提としています。
codeigniter/
├── application/
├── public/
│ └── index.php
└── vendor/
└── codeigniter/
└── framework/
└── system/
フォルダ構成が違う場合(CodeIgniterのデフォルトのフォルダ構成の場合を含む)、application/tests/Bootstrap.php
ファイルをエディタで開き、以下のパスを調整してください。
$system_path = '../../vendor/codeigniter/framework/system';
$application_folder = '../../application';
define('FCPATH', realpath(dirname(__FILE__).'/../../public').'/');
FCPATH
はindex.php
があるフォルダです。
(2015-06-12 追記)
CodeIgniter標準のフォルダ構成の場合は、以下のように変更します。
--- a/application/tests/Bootstrap.php
+++ b/application/tests/Bootstrap.php
@@ -102,7 +102,7 @@ switch (ENVIRONMENT)
* Include the path if the folder is not in the same directory
* as this file.
*/
- $system_path = '../../vendor/codeigniter/framework/system';
+ $system_path = '../../system';
/*
*---------------------------------------------------------------
@@ -230,7 +230,7 @@ switch (ENVIRONMENT)
define('BASEPATH', str_replace('\\', '/', $system_path));
// Path to the front controller (this file)
- define('FCPATH', realpath(dirname(__FILE__).'/../../public').'/');
+ define('FCPATH', realpath(dirname(__FILE__).'/../..').'/');
// Name of the "system folder"
define('SYSDIR', trim(strrchr(trim(BASEPATH, '/'), '/'), '/'));
これでインストール完了です。
テストの実行方法
PHPUnitは別途インストールしてください。
$ cd /path/to/codeigniter/
$ cd application/tests/
$ phpunit
PHPUnit 4.1.6 by Sebastian Bergmann.
Configuration read from /.../codeigniter/application/tests/phpunit.xml
.
Time: 470 ms, Memory: 3.50Mb
OK (1 test, 1 assertion)
Generating code coverage report in Clover XML format ... done
Generating code coverage report in HTML format ... done
テストの書き方
モデル
(2015-08-15 追記) setUp()メソッドのコードを更新しました。
tests/models/Inventory_model_test.php
<?php
class Inventory_model_test extends TestCase
{
public function setUp()
{
$this->resetInstance();
$this->CI->load->model('shop/Inventory_model');
$this->obj = $this->CI->Inventory_model;
}
public function test_get_category_list()
{
$expected = [
1 => 'Book',
2 => 'CD',
3 => 'DVD',
];
$list = $this->obj->get_category_list();
foreach ($list as $category) {
$this->assertEquals($expected[$category->id], $category->name);
}
}
public function test_get_category_name()
{
$actual = $this->obj->get_category_name(1);
$expected = 'Book';
$this->assertEquals($expected, $actual);
}
}
テストケースクラスはTestCase
クラスを継承します。
setUpBeforeClass()
メソッドをオーバーライドした場合は、忘れずにparent::setUpBeforeClass();
を追加してください。
データベースシーディング
ダウンロードしたファイルのapplication/libraries/Seeder.php
とapplication/database/seeds/CategorySeeder.php
にサンプルコードが含まれています。
インストールされてないので、使いたい場合は手動でコピーしてください。
Seeder
クラスは以下のように使用します。
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
$CI =& get_instance();
$CI->load->library('Seeder');
$CI->seeder->call('CategorySeeder');
}
コントローラ
(2017-02-15 追記) テストコードを更新しました。
tests/controllers/Welcome_test.php
<?php
class Welcome_test extends TestCase
{
public function test_index()
{
$output = $this->request('GET', 'welcome/index');
$this->assertContains('<title>Welcome to CodeIgniter</title>', $output);
}
}
TestCase
クラスには$this->request()
メソッドが定義されています。
他のサンプル
もっとテストを見たい場合は、以下のアプリのテストを参照願います。
なお、このアプリのコードレビューも募集しています。
まとめ
- ci-phpunit-testを使うと簡単にCodeIgniter 3.0でPHPUnitのテストを書くことができます
- CodeIgniter本体のファイルは一切変更しません
(とはいえ、実は内部的にはCodeIgniterのクラスや関数を一部変更しています)
もっと知るには?
(2015-08-25 追記)
CodeIgniter 3.0でのPHPUnitおよびci-phpunit-testの使い方について、もっと知りたい方は以下の記事もご覧下さい。
- イマドキのCodeIgniterでPHPUnit入門 - Qiita
- イマドキのCodeIgniterでPHPUnit入門(Composer不使用編) - Qiita
- CodeIgniterとPHPUnitでテストが難しいコードを簡単にテストする(オブジェクトメソッドの置換)
- ci-phpunit-testを使って和田卓人さんの『現在時刻に依存するテスト』を書いてみる
- ci-phpunit-testでsingletonなクラスを呼び出してるメソッドをテストする - Qiita
- ci-phpunit-test v0.4.0をリリースしました
- ci-phpunit-testのモンキーパッチ機能でexitを例外に変換したときのデバッグ方法
関連
Date: 2015/05/19