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

Published: 2017年7月2日 by tomsato

概要

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

コメントを書く

※ 個別に返信が必要な時のみご記入ください

※ Emailは公開されません

※ 承認されると名前・コメントが下記に表示されます

コメント一覧

最近の投稿

ビジュアルリグレッションテストについてまとめ、ネットで調べると数多くのライブラリがありどれがどんな立ち位置なのか全体像がわかりずらかったのでどんな種類があるのか入門の入門としてまとめます、またPlaywrightを使って実際に触ってみました

社内ツールなどの超小規模なAPIをGolangで実装する際にフレームワークを使うべきかを、実際にnet/httpを使った実装とフレームワークを使った実装を比較することでどれだけ優位性があるかを見ていきたいと思います。今回はフレームワークにはシンプルで使いやすそうなEchoを使うことにします。

vue-pdfを使ってNuxt.jsで作成しているアプリケーションに pdfスライドを表示させるサンプルを作成しました README.md通りに実装してもうまくいかないところがあったのでそのあたり含めてまとめます

Vue.js / Nuxt.jsにおけるログインの実装方法をまとめる Auth0やNuxt.jsのAuth Moduleとmiddlewareについて調べつつサンプルを作成することで理解を深める

コンポーネント設計について考える Atomic DesignやPresentational Component, Container Componentについてまとめつつ 自分だったらVue.js / Nuxt.jsでどういうコンポーネント設計にするかについてまとめます

カテゴリ一覧

タグ一覧