Selenium, Jenkins, Ruby(Capybara) の E2E テスト環境基盤を Docker で構築したときの知見のまとめ(環境編)

## 概要

以下の図のような `E2E` テスト環境基盤　を構築しました。

![compose.jpg](https://qiita-image-store.s3.amazonaws.com/0/101975/5c1928ca-1b2e-3036-368d-32d7088813db.jpeg)


これは以下からコードを `clone` し `bash deploy.sh` を実行すると環境が出来上がったりします。
※`docker`, `docker-compose` が使えることが前提です

* [Github: toririn/e2e_docker](https://github.com/toririn/e2e_docker)

なんでこんな面倒な構成をするんだという所もありますが、とりあえず環境を作ってみたという所が大きいです。

いつの間にやら `docker-compose` の書き方も変わったりしていたのでいい勉強になりました。

ということでこの **テスト環境基盤の説明・デプロイ方法**と、 **`docker-compose.yml` の書き方**を記事にしました。

ただし内容が多いので2つの記事に分けています。具体的には下記のようになっています。

### **この記事**に書かれていること

* `Selenium`, `Ruby Script`, `Jenkins` によるE2Eテスト環境基盤の説明
* 上記コンテナ達のデプロイ方法
* 上記 `Jenkins(docker)` の起動・初期設定・ジョブの実行
* まとめ


### **もう一つの記事**に書かれていること

[Selenium, Jenkins, Ruby(Capybara) の E2E テスト環境基盤を Docker で構築したときの知見のまとめ(書き方編)](http://qiita.com/toririn/items/977c967a42a906e217ba)

* docker-compose の記載方法の説明
  * version
  * services
  * image
  * build
    * context
    * dockerfile
    * args
  * ports
  * volumes
  * links
  * depends_on
  * environment
* まとめ

という事でこちらは **環境編** になります。宜しくお願いします。

---

## E2Eテスト環境基盤の説明

今回作った環境基盤は以下の図のような動きを行います。

![compose2.jpg](https://qiita-image-store.s3.amazonaws.com/0/101975/5bd1c12b-2476-1878-49e8-c020e8ef0aa6.jpeg)

`jenkins` の `image` があるのは、簡単に誰でもテストを起動できるようにするためです。
`jenkins` で `job` さえ作っていたらボタンぽちーですからね。

ちなみにこいつのデバッグ方法は以下のようにすることで実現できます。

* `ruby/set_env.sh` の値を書き換える

```bash:ruby/set_env.sh
- export SELENIUM_HOST=selenium
+ export SELENIUM_HOST=localhost
export SELENIUM_PORT=4444
```

何故これで実現できるかというと、　`selenium` のコンテナの `4444` ポートをホスト側の `4444` ポートにフォワディングしているためです。

---

## デプロイ方法

### 前提

* `docker`, `docker-compose` が使えることが前提です。
* 各 `docker` のバージョンですが、少なくとも下記のバージョンでの動作は確認済みです。古いバージョンは動かないかと思いますので `upgrade` してください

```bash
$ docker -v
Docker version 1.12.1
$ docker-compose -v
docker-compose version 1.9.0
```

* 以下のようなときは `docker-compose.yml` を書き換えてください。
  * `4444`, `18080`, `50000` **ポートを他のシステムが使用している**
  * `selenium`, `ruby`, `jenkins` という**名前のコンテナが既に存在する**

---

### コンテナの作成

* ソースコード一式を `clone` してください

```
git clone https://github.com/toririn/e2e_docker.git
```

* `ruby/set_env.sh` の値を適宜書き換えてください
  * `SELENIUM_HOST`: `ruby` コンテナで使用する `selenium` コンテナの接続先IPアドレスのエイリアス。特に変える必要はないです。
  * `SELENIUM_PORT`: `ruby` コンテナで使用する `selenium` コンテナの接続先ポート番号。特に変える必要はないです。
  * `DOCKER_PASSWORD`: `ruby` コンテナの `root` ユーザのパスワード値。 `jenkins` コンテナからの `ssh` 接続で利用する。

* `clone` したプロジェクトのルートで以下のコマンドを実行してください。

```
bash deploy.sh
```

もし使っているユーザに `docker`, `docker-compose` コマンドの権限がないのであれば以下を実行してください。

```
bash ruby/set_env.sh
sudo docker-compose up -d --build
```

※ネットワーク環境によりますが初回デプロイには10分~15分程度時間がかかります

* コンテナが作成されたか確認する

```
$ docker ps
CONTAINER ID        IMAGE                                     COMMAND                  CREATED              STATUS              PORTS                                               NAMES
7d0f930bd7b8        e2edocker_ruby                            "/usr/sbin/sshd -D"      About a minute ago   Up About a minute   22/tcp                                              ruby
c18373b1afbf        selenium/standalone-firefox-debug:3.0.1   "/opt/bin/entry_point"   About a minute ago   Up About a minute   4444/tcp, 0.0.0.0:5900->5900/tcp                    selenium
3f42ddf0f2a2        e2edocker_jenkins                         "/bin/tini -- /usr/lo"   About a minute ago   Up About a minute   0.0.0.0:50000->50000/tcp, 0.0.0.0:18080->8080/tcp   jenkins
```

うまく作成出来ていたら上記のようになるかと思います。

これにてコンテナの作成は完了です。

---

### 廃棄方法

もしこのコンテナの作成に失敗したり、不要になってすべて削除したいときは以下のコマンドを実行してください

* clone したプロジェクトのロートに移動してコマンドを実行

```
bash down.sh
```

* `docker`, `docker-compose` の権限がユーザにない場合は下記

```
sudo docker-compose down
```

---

## Jenkins の設定

### 初期設定

* 以下の URL にアクセスする

http://localhost:18080/login?from=%2F

![jenkins.PNG](https://qiita-image-store.s3.amazonaws.com/0/101975/b6b616f5-f0b1-f55e-3785-f8d8a048350d.png)

* `Admin Password` を入力する

`Admin Password` は下記コマンドで表示できます

```
docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
#=> abcdefff1111
```

* plugin の install をする

しなくてもいいですが特に理由がないならしておきましょう

* ユーザを作成する

画面の内容に従いユーザのIDとパスワードを入力する

![create_user.PNG](https://qiita-image-store.s3.amazonaws.com/0/101975/2b373c4e-c92c-6549-bedc-f5a601fbff27.png)


* jenkins をスタートする

`start using jenkins` というボタンを押すと jenkins　のスタート画面へ飛びます

---

### ジョブの作成

* 下記から新しいジョブを作成します。

![new_item.PNG](https://qiita-image-store.s3.amazonaws.com/0/101975/c077e3d3-cfd8-a2db-dea5-35cf84519b23.png)


* ジョブの設定の `build` から `Execute shell` を選択して以下のコードを貼り付けます

```
sshpass -p ${DOCKER_PASSWORD} ssh root@ruby "cd /usr/src/app && bundle && bundle exec rspec spec/features/tests/test.feature"
```

![new_job.PNG](https://qiita-image-store.s3.amazonaws.com/0/101975/e49bf141-5893-914b-7770-af608b148ef7.png)


※ 本来 `ssh` でコンテナに接続しても環境変数の値は引き継がれませんが、無理やり環境変数を引き継ぐようにしています。[参考](https://github.com/toririn/e2e_docker/blob/master/ruby/Dockerfile#L16-L17)


* `Save` を押してジョブを保存します

---

### `sshpass` コマンドを使えるようにする

`jenkins` のジョブで `ssh` を使えるようにするため、一度 `ruby`　<=> `jenkins`　間を `ssh` で接続しておきます
※`sshpass` を使う故の弊害です。`SSH plugin` や `rsa` で `ssh` を使うようにしていたらこれはする必要ないかと思います！


* `jenkins` コンテナに入る

```
docker exec -it jenkins /bin/bash
```

* `ruby` コンテナに `ssh` で接続する

```
ssh root@ruby -p 22
#=> yes
```

* `jenkins` コンテナを抜ける

```
exit
```

以上で　`jenkins` の設定は完了です。

---

## 自動テストを実行する

* 作成したジョブを実行します

* 自動テストが走りたくさんの警告と共に（おい）結果が出力されます。

```
サンプル
  googleで検索ができること
/usr/local/lib/ruby/gems/2.4.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/capabilities.rb:225: warning: method redefined; discarding old proxy=
/usr/local/lib/ruby/gems/2.4.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/capabilities.rb:47: warning: previous definition of proxy= was here
/usr/local/lib/ruby/gems/2.4.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/w3c_capabilities.rb:175: warning: method redefined; discarding old proxy=
/usr/local/lib/ruby/gems/2.4.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/w3c_capabilities.rb:53: warning: previous definition of proxy= was here
/usr/local/lib/ruby/gems/2.4.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/default.rb:125: warning: method redefined; discarding old proxy
    * googleを訪問 -> * googleのページが表示されている -> * 「長谷川豊」で検索する -> * 処理を待つ -> * 検索結果のページが表示されている

Top 1 slowest examples (26.27 seconds, 100.0% of total time):
  サンプル googleで検索ができること * googleを訪問 -> * googleのページが表示されている -> * 「長谷川豊」で検索する -> * 処理を待つ -> * 検索結果のページが表示されている
    26.27 seconds ./spec/features/tests/test.feature:5

Finished in 26.28 seconds (files took 0.81951 seconds to load)
1 example, 0 failures

Randomized with seed 53862

Finished: SUCCESS
```

以上です！

---

### まとめ

* `Selenium` + `Ruby Script` + `Jenkins` による E2E自動テストの環境を `Docker` にて構築しました。
* 構築には `docker-compose` を使い一元的に各コンテナを管理するようにしました。
* この記事にはそのデプロイ方法を記載しました。

もし記載している **`docker-compose` の書き方に興味がありましたら下記を参照ください。**

[Selenium, Jenkins, Ruby(Capybara) の E2E テスト環境基盤を Docker で構築したときの知見のまとめ(書き方編)](http://qiita.com/toririn/items/977c967a42a906e217ba)