概要
前回Codeceptionについてどんなテストがあるのかと実際に動くものを見てどんな感じなのかイメージを持ったので
今回は実際にテストが無いプロジェクトに対してCodeceptionを追加してみる
ゼロスタートということでどのように追加していくのか、またファイル構成を見ることを中心に解説を行う
作り方に関して
Codeceptionの作り方に関していくつか筆者独自の考えを入れているところがあるので
そのあたりについて最初に説明しておく
モックについて
AspectMockを使う、composerで入れる時はcodeception/aspect-mockを指定してあげる形になっていて、見て分かる通りCodeceptionを作っている人がAspectMockも作っている
AspectMockはモッキングフレームワークで簡単にメソッ ドのレスポンス結果を定義することができる
使い方はこのページを見れば事足りる
普通じゃないモッキングフレームワークAspectMockがパワフル過ぎる
テスト形式について
CodeceptionはCeptとCestというテスト形式を書くことができる
Codeception.docs.ja – Cept、Cest、テスト形式
Ceptの例
<?php $I = new AcceptanceTester($scenario); $I->wantTo('login to website');
Cestの例
<?php class BasicCest { public function _before(\AcceptanceTester $I) { } public function _after(\AcceptanceTester $I) { } // tests public function tryToTest(\AcceptanceTester $I) { } }
このようにCest形式はシナリオ駆動型テストのアプローチとオブジェクト指向設計を組み合わせている
またテストシナリオをグループにまとめることもできるのでCest形式を前提としてテストを作成していくこととする
テストの種類について
今回は単体テストと機能テストを書いていくことを重視する
実際のサービスにCodeceptionを入れる時にも、3種類全部取り入れるべきかはリソースとリスクを考慮した上で判断する
判断例
- 時間が無いので単体テストだけ
- マネージャーにシナリオテストを見せることも考えて単体テストと受け入れテストだけ
- 開発者でシナリオテストしたいので単体テストと機能テストだけ
- 時間の余裕があってやる気もあるので3種類全部テストする
ゼロからCodeceptionを追加する
準備
$ php -v PHP 5.6.30 (cli) (built: Jan 19 2017 08:09:42) $ cat /etc/redhat-release CentOS release 6.8 (Final)
ソースコード準備
$ git clone https://github.com/tomsato/codeception_test $ cd codeception_test $ composer install
サンプルを動かす
$ sudo php -S 0.0.0.0:80 -t public public/index.php
この状態で「http://localhost:80/hoge/test」にアクセスすると
「Home testtttt.」が表示される(この辺りは適当)
すでにテストは存在しているので消す
$ rm -rf codeception.yml tests/ $ composer remove --dev codeception/codeception herloct/codeception-slim-module codeception/aspect-mock
単体テスト追加
composerで必要なpkgを追加
$ composer require --dev codeception/codeception herloct/codeception-slim-module codeception/aspect-mock
bootstrapでCodeceptionを一式準備する
$ vendor/bin/codecept bootstrap
ファイル構成
// 特にファイル構成知りたく無いならここはスキップ $ sudo yum install tree // 一部抜粋 $ tree tests/ tests/ ├── acceptance ← 受け入れテストを書いていくディレクトリ ├── acceptance.suite.yml ├── functional ← 機能テストを書いていくディレクトリ ├── functional.suite.yml ├── unit ← 単体テストを書いていくディレクトリ └── unit.suite.yml ├── _output ├── _support ├── _data ※ ymlファイルにはどんなモジュールを使うかなど設定を書いていく
テストを実行する(何もテストを作っていないので空)
$ ./vendor/bin/codecept run ...中略... No tests executed!
ユニットテストを作成する
src/Controller/SampleApp.php のテストを作成するために以下のコマンドを叩く $ ./vendor/bin/codecept generate:test unit SampleApp
中身は以下をコピペして貼り付ける
public function testResponse() { // Modelクラスをモック化する test::double('Myapp\Model\SampleModel', [ 'getStr' => 'hoge' ]); $env = Environment::mock([ 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/hoge/test' ]); $request = Request::createFromEnvironment($env); $response = new Response(); $hoge = new SampleApp(new Container()); $result = $hoge->index($request, $response, $args = []); $this->assertEquals(200, $result->getStatusCode()); }
・Controllerを実行してstatus codeが200で返ってくることをテストしている
・AspectMockを使ってgetStr関数のレスポンスを「hoge」になるように定義している
テスト実行前に読み込まれるファイルを作成する
$ touch tests/unit/_bootstrap.php tests/functional/_bootstrap.php tests/acceptance/_bootstrap.php // autoloadの読み込み、AspectMockの準備 $ vim tests/_bootstrap.php <?php require __DIR__.'/../vendor/autoload.php'; $kernel = \AspectMock\Kernel::getInstance(); $kernel->init([ 'debug' => true, 'includePaths' => [__DIR__.'/../src'], 'cacheDir' => __DIR__.'/cache/AspectMock', ]); // テスト実行前に_bootstrap.phpを読み込むように設定する $ vim codeception.yml + settings: + bootstrap: _bootstrap.php // 必要なディレクトリを準備 $ mkdir tests/cache
単体テスト実行
$ ./vendor/bin/codecept run unit Unit Tests (1) -------------------------------------------------------------------------------------- OK SampleAppTest: Response (0.04s) ----------------------------------------------------------------------------------------------------- OK (1 test, 1 assertion)
機能テスト追加
// slimフレームワークを使っているのでslimのモジュールを追加するように設定を追加する $ vim tests/functional.suite.yml actor: FunctionalTester modules: enabled: - \Helper\Functional - \Herloct\Codeception\Module\Slim: container: tests/container.php - REST: depends: \Herloct\Codeception\Module\Slim // containerの準備(slimでは無い場合はいらない) $ vim tests/container.php <?php require __DIR__.'/../vendor/autoload.php'; use Psr\Container\ContainerInterface; use Slim\App; use Slim\Container; $container = new Container([ App::class => function (ContainerInterface $c) { $app = new App($c); // routes and middlewares here require __DIR__ . '/../conf/routes.php'; return $app; } ]); return $container;
テストケースをジェネレートする
$ ./vendor/bin/codecept generate:cest functional SampleApp // tryToTestメソッドを以下に置き換える $ vim tests/functional/SampleAppCest.php public function ページを開いた時にHomeが表示されていることを確認できる(FunctionalTester $I) { $I->amOnPage('/hoge/test'); $I->seeResponseCodeIs(200); $I->see('Home testttt', '.main'); }
テストを実行
$ ./vendor/bin/codecept run functional Functional Tests (1) -------------------------------------------------------------------------------- OK SampleAppCest: ページを開いた時にhomeが表示されていることを確認できる (0.06s) ----------------------------------------------------------------------------------------------------- OK (1 test, 2 assertions)
・/hoge/testを開く
・status codeが200であることを確認する
・HTMLのmainクラスに「Home testttt」が含まれていることを確認する
このようにgenerate関数でテストケースを追加していくことによってテストを拡充できる
コメントを書く
コメント一覧