CodeceptionをDockerでもCIでも動かしてみる

## はじめに（2018-03-21 更新）

2016年7月、[Symfony Meetup #13](https://symfony.doorkeeper.jp/events/47980)での[@kseta](http://qiita.com/kseta)さんのLTに触発されて、Codeceptionをとにかく動かしてみました。
お急ぎの方は、exampleを作りましたので、cloneするなりして動かしみてください。
https://github.com/imunew/docker-codeception-example （2018−03−21更新）

## 構成
ざっくりと構成は以下のとおりです。

- Webアプリケーションは、[Symfony Demo Application](https://github.com/symfony/symfony-demo)をそのまま利用
- Codeceptionのコードは、[Codeception/symfony-demo](https://github.com/Codeception/symfony-demo)を参考に
- 受入テスト（Acceptance tests）のみを対象に
- `PHPBrowser`ではなく、`WebDriver` + `chromedriver`で

## Docker環境（2018-03-21 更新）
ざっくりと構成は以下のとおりです。

- Symfony Demo Application は、公式の[PHPコンテナ](https://hub.docker.com/_/php/)をベースに
- Selenium + ChromeDriverは、公式の[Seleniumコンテナ](https://hub.docker.com/r/selenium/standalone-chrome-debug/)をそのまま利用

主要なファイルは下記のとおり。

```docker-compose.yml
version: '3.2'
services:
  php:
    build: ./docker/php
    volumes:
      - ./:/var/www/symfony.demo
    working_dir: /var/www/symfony.demo
    ports:
      - "80:80"
    networks:
      main:
        aliases:
          - symfony.demo

  selenium:
    image: 'selenium/standalone-chrome-debug'
    volumes:
      - ./:/data
    ports:
      - "4444:4444"
      - "5900:5900"
    privileged: true
    networks:
      main:
        aliases:
          - selenium.demo

networks:
  main:

```

```./docker/php/Dockerfile
FROM php:7-apache

ENV DEBIAN_FRONTEND noninteractive

RUN a2enmod rewrite

RUN apt-get update && apt-get install -y git zlib1g-dev libicu-dev g++ vim

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer

RUN docker-php-ext-configure intl
RUN docker-php-ext-install intl

ADD date.ini /usr/local/etc/php/conf.d/date.ini

ADD ./symfony-demo.conf /etc/apache2/sites-available/symfony-demo.conf
RUN a2ensite symfony-demo.conf
RUN a2dissite 000-default.conf

EXPOSE 80
```

### VNCでブラウザの動きを確認しながらテスト実行
READMEにも書きましたが、selenium/standalone-chrome-debugは、VNCサーバーがセットアップされているので、Mac標準のVNCクライアントから接続して、ブラウザの動きを確認しながらテスト実行することができます。

![codeception-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/26422/dc08969b-0d00-3537-8175-04f9c543045b.gif "codeception-demo.gif")


### ハマったところ（解決済み 2018-03-21更新）
相互参照になる場合は、`networks`を使うことで回避することが可能です。
下記のブログが参考になりました。

- [Two-way link with Docker Compose – Yani Iliev – Medium](https://medium.com/@yani/two-way-link-with-docker-compose-8e774887be41)

~~seleniumコンテナに`extra_hosts`を追加してますが、この部分が解決できず、10時間ほど費やしてしまった気がします。~~

- chromeブラウザから、`http://symfony.demo`にアクセスできないといけないので、seleniumコンテナ~~の`/etc/hosts`~~でホスト名を解決する必要あり
- `php`コンテナから、`selenium`コンテナをlinkしているので、その逆をしようとすると、循環参照になってしまうとのことでエラーになる
- ~~本当はextra_hostsに内部IPを書きたくない。誰かスマートなやり方教えてください。~~

## CI環境（v1からv2に 2018-03-21更新）
ざっくりと構成は以下のとおりです。

- circle-ciを利用
- ~~Dockerコンテナと違い、All-In-One構成~~
- ~~ChromeDriverはインストール済み~~
- ~~Seleniumは、ダウンロード＆インストール＆バックグラウンド実行~~
- ローカル同様、CI上でも`docker-compose`を利用

```..circleci/config.yml
version: 2
jobs:
  build:
    machine: true
    working_directory: ~/project
    steps:
      - checkout
      - run:
          name: Install Docker Compose
          command: |
            pip install --upgrade pip
            pip install docker-compose
      - run:
          name: Setup environment
          command: |
            docker-compose up -d --build
            docker-compose exec php composer install --no-interaction
            docker-compose exec php bin/console cache:clear --env=prod --no-debug
            docker-compose exec php chmod -R a+w var/cache var/sessions
      - run:
          name: Run tests
          command: |
            docker-compose exec php bin/codecept run acceptance
            cp -R tests/_output /tmp/artifacts/
      - store_artifacts:
          path: /tmp/artifacts
```

### ハマったところ（2018-03-21更新）
- ~~Seleniumはインストール済みってしばらく勘違いしてた~~
- Codeceptionのverboseでは、アプリが動かない原因はよく分からない
- xdebug有効にしてると、`./tests/_output/XxxxxCept.fail.png`にエラーの詳細が表示されているので助かった
- 困ったら、`Rebuild with SSH`でコンテナにログインしてデバッグ

### これから試したいこと
- CircleCIでもVNC接続 [Interact with the browser over VNC](https://circleci.com/docs/browser-debugging/#interact-with-the-browser-over-vnc)

## おわりに（2018-03-21更新）
~~Nightmare(v2)で消耗気味なので、別の候補を探している最中ではありますが、少なくてもSelenium系にはしたいと考えています。~~
`Codeception`は、多少、独特のルールがありますが、普段PHPでサーバーサイドのコードを書いているエンジニアでもとっつきやすいと感じました。
`Codeception`の中身については、また別の投稿で書ければと思います。