CircleCIで始めるCakePHP3アプリの継続的インテグレーション(2) - MySQL DBを用いたテスト

CircleCIで始めるCakePHP3アプリの継続的インテグレーション(2) - MySQL DBを用いたテスト

月末にウワサされている某イベントに期待を膨らませているtanakaです。

前回の記事(CircleCIで始めるCakePHP3アプリの継続的インテグレーション)に続いて、 データベースを使ったテストをCircleCIで実行できるようにします。

目次

  • 前回のおさらい
  • Step 0)設定の管理について
  • Step 1) ローカル開発環境でMySQL接続設定を行う
  • Step 2) データベースを使ったテスト(1) マイグレーションファイルを作成する(accountsテーブルの作成)
  • Step 3) データベースを使ったテスト(2) 実装およびテスト
  • Step 4) CircleCI でMySQLデータベースを使ったテストを行う
  • まとめ

前回同様、ローカル環境でテストできるようにしてから、CircleCIの設定を書きますので、「ローカルではできてるよ!」という場合はStep 4までジャンプしてOKです(^_^) 今回はgit操作は省略します。

前回のおさらい

前回の記事では、 CakePHP3 アプリを新規作成してから、GitHubリポジトリにPushしました。

次にCircleCIアカウントを作成してビルドできるようにしました。

最後に circle.yml を追加して、ビルド設定をカスタマイズしました。

今回はこの続きで、データベーステストできるようにします。

Step 0)設定の管理について

本題に入る前に、データベース接続を含む、環境ごとに異なる設定をどう扱うか、について説明します。 composer create-projectでCakeアプリを作成した場合、app.php 内の以下の設定を環境変数で定義できるようになっています。

  • DEBUG
  • DATABASE_URL
  • DATABASE_TEST_URL
  • SECURITY_SALT
  • その他ログ設定や送信メールサーバ設定など

そこでこの記事ではapp.phpを編集せず vlucas/phpdotenv - GitHubを使ってローカル開発環境の環境変数設定を行い、CircleCI環境ではcircle.ymlに設定することにします。(実運用環境ではphpdotenvかWebサーバのVirtualHost設定から渡す方法などが選べます) phpdotenvを使い始める初期設定は以下の通りです。

ライブラリをインストールします。

$ composer require vlucas/phpdotenv

環境変数をCakePHPアプリで読み込む

app.default.php, app.php を読み込む前に config/.env を読み込んで環境変数をPHPセッション内に定義しておきます。

// `config/bootstrap.php` 69行目あたり
if (file_exists(__DIR__ . DS . '.env')) {
    $dotEnv = new Dotenv\Dotenv(__DIR__);
    $dotEnv->load();
}

.gitignore にも1行追加しておきます。

/config/.env

DEBUG のデフォルト値を false にする

app.php, app.default.php の12行あたりに記述されているDEBUG設定がtrueになっていますが、このまま実運用環境にデプロイするとエラー情報などが見えてしまってまずいことになるので、デフォルトfalseに変更しておきます。

// `app.php`, `app.default.php` の12行目あたり
    'debug' => filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),
//  ↓
    'debug' => filter_var(env('DEBUG', false), FILTER_VALIDATE_BOOLEAN),

config/.env に以下を記述すれば、今まで通りローカル開発環境でデバッグ情報が表示されるようになります。

# `config/.env`
DEBUG=true

以上でMySQL接続設定の前準備は終わりです。

Step 1) ローカル開発環境でMySQL接続設定を行う

以下のような感じでDBと接続ユーザを作ります。いまデータベースを新規につくるのであればutf8mb4を指定した方がよいです。

$ mysql -uroot -p
mysql> CREATE DATABASE cisample CHARSET utf8mb4;
mysql> CREATE DATABASE cisample_test CHARSET utf8mb4;
mysql> /* MySQL 5.7 のデフォルトパスワードポリシーエラーにされないサンプルパスワードです */
mysql> GRANT ALL ON cisample.* TO 'cisample'@'localhost' IDENTIFIED BY 'Pa$$w0rd';
mysql> GRANT ALL ON cisample_test.* TO 'cisample'@'localhost' IDENTIFIED BY 'Pa$$w0rd';

自動テスト用データベースもここで作ります。

作成したデータベースとユーザを config/.env に設定します。

DATABASE_URL="mysql://cisample:Pa$$w0rd@localhost/cisample?encoding=utf8mb4&timezone=UTC&cacheMetadata=true"
DATABASE_TEST_URL="mysql://cisample:Pa$$w0rd@localhost/cisample_test?encoding=utf8mb4&timezone=UTC&cacheMetadata=true"

mysql://...の部分がMySQLデータベース接続のためのDSN文字列です。

もう一度ブラウザで開いてみて、DB接続ができていることを確認してください。

20161020tanaka-circleci-database.png

もしうまくいかない場合はキャッシュをクリアするといいかもしれません。

bin/cake cache clear_all

Step 2) データベースを使ったテスト(1) マイグレーションファイルを作成する(accountsテーブルの作成)

データベースに接続できるようになりましたので、テーブルを作成しましょう。 重要なのはテーブル作成もコード化して、CircleCIでも実行できるようにすることです。そのためにCakePHPにはMigrationsの仕組があります。

composer create-project でCakePHPアプリを作成した場合、cakephp/migrationsがインストール済みなので、早速テーブルを作っていきましょう。

以下のようなテーブルを作ります。

  • email: varchar(255) (UNIQUE INDEX)
  • status: varchar(10) 'enable' もしくは 'disable'
  • password: varchar(100)
  • created: datetime
  • modified: datetime

以下のコマンドでスキーマファイルの作成(1行目)とデータベースへの反映(2行目)を行います。(説明単純化のためコマンドにしてます)

$ bin/cake bake migration CreateAccounts email:string[255]:unique status:string[10] password:string[100] created modified
$ bin/cake migrations migrate

データベースにアクセスするとaccountsテーブルが作成されているはずです。

Step 3) データベースを使ったテスト(2) 実装およびテスト

簡単な例として、有効なアカウント(Accounts.status = 'enable'を取得するカスタムFinderを作ってそれをテストしてみました。

詳細は説明しませんが、bin/cake bake model Accountsでコードを生成してから、AccountsTable::findEnable()の実装コードとテストコードを追加しています。phpunitを実行すると数が増えているはずです。

20161020tanaka-circleci-database-02.png

Step 4) CircleCI でMySQLデータベースを使ったテストを行う

Step 3までで、ローカル開発環境でMySQL DBを使ったテストができるようになりましたが、CircleCIでもテスト実行できるようにするための設定を追加すると以下になります。

circle.yml

machine:
  php:
    version: 7.0.11
  services:
    - mysql
  environment:
    DEBUG: true
    DATABASE_URL: "mysql://ubuntu:@localhost/cisample?unix_socket=/var/run/mysqld/mysqld.sock&encoding=utf8mb4&timezone=UTC&cacheMetadata=true"
    DATABASE_TEST_URL: "mysql://ubuntu:@localhost/cisample_test?unix_socket=/var/run/mysqld/mysqld.sock&encoding=utf8mb4&timezone=UTC&cacheMetadata=true"
dependencies:
  cache_directories:
    - ~/.composer/cache
  pre:
    - composer config -g github-oauth.github.com $GITHUB_ACCESS_TOKEN
  override:
    - composer install --dev --no-interaction
  post:
    - mysql -u ubuntu -e "CREATE DATABASE cisample CHARSET utf8mb4;"
    - mysql -u ubuntu -e "CREATE DATABASE cisample_test CHARSET utf8mb4;"
    - bin/cake migrations migrate
test:
  override:
    - mkdir -p $CIRCLE_TEST_REPORTS/phpunit
    - vendor/bin/phpunit --configuration phpunit.xml.dist --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit.xml

追加したところは以下の通り。

  services:
    - mysql

MySQLサーバを起動する設定です。

  environment:
    DEBUG: true
    DATABASE_URL: "mysql://ubuntu:@localhost/cisample?unix_socket=/var/run/mysqld/mysqld.sock&encoding=utf8mb4&timezone=UTC&cacheMetadata=true"
    DATABASE_TEST_URL: "mysql://ubuntu:@localhost/cisample_test?unix_socket=/var/run/mysqld/mysqld.sock&encoding=utf8mb4&timezone=UTC&cacheMetadata=true"

環境変数を定義します。ローカル開発環境の.envと一緒です。ubuntuというユーザでパスワードなしで接続できるので、そのまま使っています。

unix_socket=/var/run/mysqld/mysqld.sock を記述しないと接続ができなかったので追加しています。

  cache_directories:
    - ~/.composer/cache

今回のテストとは関係ないですが、composer installの時間が短縮できるので追加。

  post:
    - mysql -u ubuntu -e "CREATE DATABASE cisample CHARSET utf8mb4;"
    - mysql -u ubuntu -e "CREATE DATABASE cisample_test CHARSET utf8mb4;"
    - bin/cake migrations migrate

テストを実行する前にデータベースとテーブルを作成しています。

まとめ

  • 環境ごとの設定をphpdotenvで管理するように設定しました
  • ローカル開発環境でデータベース作成からカスタムファインダーの実装とテストまでコードを書きました
  • CircleCIでもMySQL DBを使ったテストができるようにしました

CircleCIに限らず、最近流行のCIサービスは設定のほとんどを設定ファイルに記述するので、ノウハウを伝えやすくていいですね。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ