プロジェクトにCodeceptionテストをゼロから追加する


■ 目次

  1. 概要
  2. 作り方に関して
  3. ゼロからCodeceptionを追加する
    1. 準備
    2. 単体テスト追加
    3. 機能テスト追加

■ 概要

前回Codeceptionについてどんなテストがあるのかと実際に動くものを見てどんな感じなのかイメージを持ったので

今回は実際にテストが無いプロジェクトに対してCodeceptionを追加してみる

PHP 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関数でテストケースを追加していくことによってテストを拡充できる


Be First to Comment

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です