DockerとCodeceptionを使ってE2Eテストを簡単に実行もCIもできる環境を作ってみた。

# 概要

三行で

- codeception超便利だけど、seleniumの環境用意するの超めんどくさい
- dockerにイメージある！せや！全部dockerで作ればええんや！
- できた。

https://github.com/MiuraKatsu/codeception_easy_acceptance

# 使い方

githubのリポジトリをforkして適当に修正して、```make```叩けばテストが回ります。

## インストール
dockerとdocker-composeは入れておいてください。

## Url

param.phpでテスト先のURLを指定しています。

``` php:tests/param.php
<?php

    $TARGET_URL = 'https://codeception.com/';

    return [
        'TARGET_URL' => $TARGET_URL
    ];
```

環境によって接続先を変えたい、みたいなときはここをいじってみてください。

## Environments

acceptance.suite.ymlでブラウザ環境を３種類(PHP Browser,chrome,firefox)設定しています。WebDriverにわたすパラメータをいじりたいときはここをいじってみてください。

## Test

tests/acceptance/以下にテストは書きます。
```@env```アノテーションでブラウザの種類を分けて実行できます。

## Run

Makefileに実行コマンドが書いてあるので、```make```一発でdockerが立ち上がり、テストが回ります。初回はimageをpullしてくるので時間がかかると思います。

```
% make
/usr/bin/make up run-tests
docker-compose up -d chrome firefox
Creating network "codeception_easy_acceptance_default" with the default driver
Creating codeception_easy_acceptance_firefox_1 ... done
Creating codeception_easy_acceptance_chrome_1  ... done
docker-compose run codecept run -x optional -vv --html=_report.html --env firefox --env chrome --env phpbrowser -g all
Starting codeception_easy_acceptance_chrome_1  ... done
Starting codeception_easy_acceptance_firefox_1 ... done
Codeception PHP Testing Framework v2.3.9
Powered by PHPUnit 6.5.7 by Sebastian Bergmann and contributors.
[Groups] all

  Rebuilding AcceptanceTester...

Acceptance (firefox) Tests (1) ----------------------------------------------------------------------------------------------------------------
Modules: WebDriver
-----------------------------------------------------------------------------------------------------------------------------------------------
⏺ Recording ⏺ step-by-step screenshots will be saved to /project/tests/_output/
Directory Format: record_5b7a298bc1f10_{testname} ----
  Printing HTML report into _report.html
FirstCest: Test top page
Signature: FirstCest:tryToFirefoxTest
Test: tests/acceptance/FirstCest.php:tryToFirefoxTest
Scenario --
 I am on page "/"
  [GET] https://codeception.com/

 I see "codeception","//*[@id="home-hero"]/div/h1"
 I grab text from "//*[@id="home-hero"]/div/h1"
  Codeception
 I make screenshot "top"
  Screenshot saved to /project/tests/_output/debug/top.png
 PASSED

-----------------------------------------------------------------------------------------------------------------------------------------------
⏺ Records saved into: file:///project/tests/_output/records.html
  Rebuilding AcceptanceTester...

Acceptance (chrome) Tests (1) -----------------------------------------------------------------------------------------------------------------
Modules: WebDriver
-----------------------------------------------------------------------------------------------------------------------------------------------
⏺ Recording ⏺ step-by-step screenshots will be saved to /project/tests/_output/
Directory Format: record_5b7a2995e2ed4_{testname} ----
FirstCest: Test top page
Signature: FirstCest:tryToChromeTest
Test: tests/acceptance/FirstCest.php:tryToChromeTest
Scenario --
 I am on page "/"
  [GET] https://codeception.com/

 I see "codeception","//*[@id="home-hero"]/div/h1"
 I grab text from "//*[@id="home-hero"]/div/h1"
  Codeception
 I make screenshot "top"
  Screenshot saved to /project/tests/_output/debug/top.png
 PASSED

-----------------------------------------------------------------------------------------------------------------------------------------------
⏺ Records saved into: file:///project/tests/_output/records.html
  Rebuilding AcceptanceTester...

Acceptance (phpbrowser) Tests (1) -------------------------------------------------------------------------------------------------------------
Modules: PhpBrowser, \Helper\Acceptance
-----------------------------------------------------------------------------------------------------------------------------------------------
Recorder is disabled, no available modules
FirstCest: Test top page
Signature: FirstCest:tryToPhpbrowserTest
Test: tests/acceptance/FirstCest.php:tryToPhpbrowserTest
Scenario --
 I am on page "/"
  [Request Headers] []
  [Page] /
  [Response] 200
  [Request Cookies] []
  [Response Headers] {"Date":["Mon, 20 Aug 2018 02:38:21 GMT"],"Content-Type":["text/html; charset=utf-8"],"Transfer-Encoding":["chunked"],"Connection":["keep-alive"],"Set-Cookie":["__cfduid=dbe0d03b4f6442e1c36f1e8dcf379c8661534732701; expires=Tue, 20-Aug-19 02:38:21 GMT; path=/; domain=.codeception.com; HttpOnly; Secure"],"Last-Modified":["Wed, 01 Aug 2018 08:03:25 GMT"],"Access-Control-Allow-Origin":["*"],"Expires":["Mon, 20 Aug 2018 02:08:39 GMT"],"Cache-Control":["max-age=600"],"X-GitHub-Request-Id":["573E:6E00:32C3A3:39ACE3:5B7A204F"],"Via":["1.1 varnish"],"Age":["46"],"X-Served-By":["cache-nrt6147-NRT"],"X-Cache":["HIT"],"X-Cache-Hits":["2"],"X-Timer":["S1534732701.182379,VS0,VE0"],"Vary":["Accept-Encoding"],"X-Fastly-Request-ID":["02d9b183401efb5f6572fbc9d4314b4a9b80935f"],"Expect-CT":["max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct""],"Server":["cloudflare"],"CF-RAY":["44d17bb65a629469-NRT"]}

 I see "codeception","//*[@id="home-hero"]/div/h1"
 I grab text from "//*[@id="home-hero"]/div/h1"


      Codeception
 PASSED

-----------------------------------------------------------------------------------------------------------------------------------------------


Time: 17.75 seconds, Memory: 18.07MB

OK (3 tests, 3 assertions)
- HTML report generated in file:///project/tests/_output/_report.html
```

## Debug

```docker-compose run```コマンドを個別に実行すれば、```@env```,```@group```アノテーションで絞り込んだ実行もできます。

```
docker-compose run codecept run --env firefox -g onlythisone
```

seleniumのイメージ、standalone-xxxx-debugを使っているので、vncで繋がります。vncを使えば実際のブラウザの挙動が確認できます。
一応、vnc起動するコマンドもMakefileに用意しました。Macでしか動作確認はしていないです。

```
make open-vnc
```

## CI

CircleCIがdocker-composeに対応していたので、そのまま同じ環境で実行できました。
jenkinsでもtravisでもdocker-compose使えるところなら大丈夫だと思います。
試してはいないですが。

# 感想

なんにしろE2EのテストはSelenium環境の準備がめんどくさいし、ハードルを上げていると思うのですが、dockerイメージが公開されているので、これを便利に使ってE2Eテスト、みんなもっと書けばいいと思う。
codeceptionのacceptance testは書き方も簡単なので、導入は楽だと思います。

開発中のコードを使ったE2EテストをCI環境に閉じた中で実施するとか考えると、構成もめんどくさくなっちゃうので、まずは簡単にテスト環境に対してE2Eテストを実施するとかから始めてみたいと思います。