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接続ができていることを確認してください。
もしうまくいかない場合はキャッシュをクリアするといいかもしれません。
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
を実行すると数が増えているはずです。
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サービスは設定のほとんどを設定ファイルに記述するので、ノウハウを伝えやすくていいですね。