CakePHP3 を CircleCI でテストする #cakephp

概要

CakePHP3 を CircleCI でテストするようにするまとめ。 Database を使ったテストも出来るようにしています。

TL;DR

最終的な yml はこんな感じです。

version: 2
jobs:
  build:
    docker:
      - image: circleci/php:7.1.32-fpm-node-browsers
        environment:
          DATABASE_URL: "mysql://root:password@127.0.0.1/my_app?encoding=utf8mb4&timezone=UTC&cacheMetadata=true"
          DATABASE_TEST_URL: "mysql://root:password@127.0.0.1/test_myapp?encoding=utf8mb4&timezone=UTC&cacheMetadata=true"

      - image: circleci/mysql:5.7-ram
        environment:
          MYSQL_DATABASE: my_app
          MYSQL_ROOT_PASSWORD: password

    steps:
      - checkout

      - run: sudo apt update && sudo apt install libicu-dev libpng-dev
      - run: sudo docker-php-ext-install pdo pdo_mysql

      # pecl で入れたいものがあれば
      # - run: sudo pecl install grpc
      # - run: sudo docker-php-ext-enable grpc

      # composer cache
      - restore_cache:
          keys:
            - composer-v1-{{ checksum "composer.lock" }}
            - composer-v1-

      - run: composer install -n --prefer-dist

      - save_cache:
          key: composer-v1-{{ checksum "composer.lock" }}
          paths:
            - vendor

      # database setup
      - run:
          name: Waiting for MySQL to be ready
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run:
          name: Migrate
          command: |
            bin/cake migrations migrate
      - run:
          name: Create database for test
          command: mysql -h 127.0.0.1 -u root -ppassword --execute "CREATE DATABASE IF NOT EXISTS test_myapp CHARACTER SET utf8"

      # test
      - run:
          name: run tests with phpunit
          command: ./vendor/bin/phpunit --log-junit tests/_output/result.xml
      - store_test_results:
          path: tests/_output
      - store_artifacts:
          path: tests/_output

解説

Cake 用の php イメージ構築

- image: circleci/php:7.1.32-fpm-node-browsers
  environment:
    DATABASE_URL: "mysql://root:password@127.0.0.1/my_app?encoding=utf8mb4&timezone=UTC&cacheMetadata=true"
    DATABASE_TEST_URL: "mysql://root:password@127.0.0.1/test_myapp?encoding=utf8mb4&timezone=UTC&cacheMetadata=true"

circleci の php イメージを使っています。

環境変数は Cake 側でテストする際に利用するために設定しています。

- run: sudo apt-get update && sudo apt-get install -y libicu-dev libpng-dev default-mysql-client
- run: sudo docker-php-ext-install pdo pdo_mysql

必要なパッケージや拡張をインストールします。

cake や php 本体のバージョンによって必要なものが変わってくるかもしれません。

mysql クライアントはテスト用 DB を作成するために入れています(後述)。

この辺は都度やると時間もかかるので、カスタムイメージ用意したほうがいいかもしれません。

composer install やキャッシュはいつものやつって感じですね。

テスト用の DB 構築

- image: circleci/mysql:5.7-ram
  environment:
    MYSQL_DATABASE: my_app
    MYSQL_ROOT_PASSWORD: password

CircleCI 公式の MySQL を使用しています。

-ram 付はメモリ内で実行されるため、パフォーマンスが高いです。

特に理由がなければ、こちらを使うとよさそうです。

- run:
    name: Waiting for MySQL to be ready
    command: dockerize -wait tcp://localhost:3306 -timeout 1m

DB の起動を dockerize で待ちます。

CircleCI のイメージであれば、dockerize は別途インストールしなくても入っていると思います。

- run:
    name: Migrate
    command: |
      bin/cake migrations migrate
- run:
    name: Create database for test
    command: mysql -h 127.0.0.1 -u root -ppassword --execute "CREATE DATABASE IF NOT EXISTS test_myapp CHARACTER SET utf8"

Migrate をした後に、テスト用の DB を別途作成しています。

CakePHP の場合、 DB を使ったテストでは Fixture を使うことになると思います。

その際、テーブル情報のインポート (public $import = ['table' => 'articles'] みたいなの) を使うことが想定されるため、別で作成するようにしています。

あとはテストを実行して、その結果を保存しているだけです。

参考