フロントエンド・テストツール比較 Selenium #03初心者でもわかる入門編

## はじめに
[株式会社クリエイス](http://creaith.jp/)CTOの[志村](https://qiita.com/naoto1222)です。  
二回に渡り
[フロントエンド・テストツール比較 Selenium #01環境構築編](https://qiita.com/creaith/items/c138c0417470a17cc4b4)
[フロントエンド・テストツール比較 Selenium #02テスト編](https://qiita.com/creaith/items/e654fae65811a0df74f3)
をお送りしてきましたが、Selenium **ぶっちゃけ色々な種類が多すぎてわけわからんですよね？**  

[モトキ](https://qiita.com/pickles) 「WebDriverIOを使うのでインストールしてください」
志村「は？Seleniumじゃねーの？？そもそもFirefoxのアドオンでやるんじゃねーの？？」
モトキ「。。。」
こんなはずかしい会話になってしまったり。。。

ということで、今回は趣向を変えて「 **案外知らない？Seleniumの実態** 」を書いていきたいと思います。

## この記事のゴール
Seleniumの概念を理解し、自動テストを設計する際に適切なツールの選定をできるようにする

## 番外 Puppeteer
こちらも良かったらどおぞ
[フロントエンド・テストツール比較 Puppeteer #03 SEOツール作ってみた - Qiita](https://qiita.com/creaith/items/1fd1142ce3ec4c694d3c)

## そもそもSeleniumとは？
Java製のブラウザ自動実行ツールです。
ブラウザを自動実行するというところからテスト、スクレイピングの用途で使われます。

## Seleniumの歴史
Seleniumを理解するためには、まず歴史を知らないことにはお話になりません。

### 初代Seleniumの登場
 2004に米ThoughtWorks社にて作られた社内向けテストツールを元に初代Selenium(Selenium Core)が開発されました。  

*   Selenium用のテストスクリプト(HTML形式)を作成し、テスト対象のWebアプリと同じフォルダに配置します。
* テストを実行すると、Selenium Coreはテストスクリプトをブラウザ操作するためのJavaScriptに変換し、テスト対象のページにテストスクリプトを埋め込みます。
* 埋め込まれたテストスクリプトが実行され、ブラウザ操作が行われます 。  
**※2018年5月現在ではSelenium Core単体のパッケージはありません **  

### Selenium RC(Remote Control)の登場
Selenium Coreはテスト対象のサーバーにテストスクリプトを配置する必要がありましたが、
Selenium RCでは **ローカルPCに配置したテストスクリプトを利用できる** ようになりました。
Selenium RCはSelenium ServerとClient Driverで構成されており、ローカルPC上でSelenium Serverを起動することにより実現できます。

#### Selenium Server(standalone)
仮想プロキシの役割を持っており、内部的にSelenium Coreを利用しています  

#### Client Driver
テストコードをJava,Ruby,Python,Perl,PHP,.NETで記述するためのドライバが組み込まれています。  

そう！なんと **今までHTML形式にしか対応していなかったテストスクリプトが他の言語で書けるよう** になったのです！  

これによりループや条件分岐などのスクリプトが組み込めるようになりました。
 テストを実行するとSelenium Serverを経由し、テスト対象のページにアクセスします。
 返却されたHTMLにSelenium Serverはテストスクリプトを埋め込みます。 
埋め込まれたテストスクリプトが実行され、ブラウザ操作が行われます。 

### 2006年 Selenium IDE 1.0の登場
Firefoxのアドオンとして開発されました。しかも国産です。
Selenium IDEにはSelenium Coreのロジックが組み込まれており、Selenium RCを使用しなくてもローカルPCからお手軽にテスト実行を行うことができるようになりました。
Excelのマクロ記録のように、実際にブラウザを操作したものをそのままテストスクリプトに変換してくれるので、プログラム初心者でも扱いやすいようになっています。
テストスクリプトを吐き出すためだけに利用することもできます。
 ただし、テストが複雑な場合はSelenium RCを使用することになると思います。

### 2006年 WebDriverの登場 
ブラウザの進化に伴い、JavaScriptのセキュリティが強化されてきました。
これにより従来のSeleniumの「JavaScriptを埋め込むことによってブラウザ操作を行う」というテスト実行方法が難しくなってきました。
このような問題を解決するためにGoogleにより開発されたのがWebDriverです。
WebDriverはJavaScriptを介入することなく、外部のプログラムから直接ブラウザを操作するためのインターフェースです。
この時点ではSeleniumとは全く関係のないものです

### 2011年 Selenium 2.0の登場
WebDriverとSelenium RCが統合され、新しくSelenium 2.0として生まれ変わりました。
これに伴いWebDriverはSelenium WebDriverとして提供されています。
Selenium WebDriverではSeleniumのテストスクリプトをJavaScriptを介入させることなく、ブラウザ操作を直接行えるようになったことにより、様々なテストケースを実行できるようになりました。 
このSelenium WebDriverを操作してテストをするためには各言語毎のライブラリが別途必要です。
[](
これらのライブラリには、各ブラウザ向けのドライバモジュールが一緒に入っています。
)

### 2013年 Selenium IDE 2.0の登場
これまでSelenium IDEはFirefoxでしか実行できませんでしたが、IEやChromeでもテスト実行を行うことができるようになりました。
 ただしお手軽感はなく、Selenium ServerとSelenium WebDriverをインストールしなければなりません。
**※2018年5月現在まともに動かないという話をちらほら聞きます**

### 今回我々が使用したWebDriverIOとは？
node.jsからSelenium Server(standalone)を操作 + テスト用出力が選べるライブラリです。
Selenium WebDriverの代わりに利用するイメージですね。
Selenium WebDriverだけではテスト出力まで考慮出来ないので、フォーマットや出力方法を望む組合せで選べるのは大きな特徴です。
知っている人なら、MochaやChaiなどの機能を内包していると言えばわかりやすいでしょうか。

## Selenium WebDriverを操作するためのライブラリ

|言語|ライブラリ|備考|
|---|---|---|---|
|Ruby|[selenium-webdriver](https://rubygems.org/gems/selenium-webdriver/versions/2.53.0)||
|Ruby|[Capybara](https://github.com/teamcapybara/capybara)|サードパーティ製|
|PHP|[phpunit-selenium](https://packagist.org/packages/phpunit/phpunit-selenium)|サードパーティ製|
|Python|[selenium](https://pypi.org/project/selenium/)||
|Perl|[Selenium-Remote-Driver](https://github.com/teodesian/Selenium-Remote-Driver)|サードパーティ製|
|node.js|[selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver)||
|Go|[Agouti](https://github.com/sclevine/agouti) |サードパーティ製、[アグーチ](https://kotobank.jp/word/%E3%82%A2%E3%82%B0%E3%83%BC%E3%83%81-1142248)が由来？|
|C#(.NET)|[Selenium.WebDriver](https://www.seleniumhq.org/download/) ||

## Selenium Serverを介してブラウザを操作するためのライブラリ

|言語|ライブラリ|備考|
|---|---|---|---|
|PHP|[PHP-WebDriver](https://github.com/facebook/php-webdriver)|
|node.js|[WebDriverIO](http://webdriver.io/)|

## 組合せの具体例
### 前提条件
* ローカルからSeleniumサーバに向けて実行する
* ChromeDriverを用意している
* UIテストを前提とする
* サーバサイドのテストは行わない

### テストスクリプトをPHPで書きたい場合
#### Selenium Server(standalone) + phpunit-selenium + phpunit

### テストスクリプトをRubyで書きたい場合
#### SeleniumWebDriver + Capybara + Rspec
Ruby on Railsと一緒に。Rspecの代わりにminitestを使う事もできるようです。

### テストスクリプトをnode.jsで書きたい場合
#### Selenium Server(standalone) + WebDriverIO
我々が実際に扱った組合せです。
ReactやVue.jsで描画されたページに対してテストを行う想定です。
[フロントエンド・テストツール比較 Selenium #01環境構築編](https://qiita.com/creaith/items/c138c0417470a17cc4b4)
[フロントエンド・テストツール比較 Selenium #02テスト編](https://qiita.com/creaith/items/e654fae65811a0df74f3)

## 陥りやすいSeleniumの混乱ポイント
サーバーサイドの言語とSeleniumテストスクリプトの言語の両方を前提条件として明記している解説サイトはほぼありません。
ほとんどの場合がブラウザテストのみの説明ですので、決して不親切というわけではないのですが、 Unitテストという言葉がでてくると、「サーバーサイドに埋めなきゃいけないのか？」、「開発言語がPHPだからPHPでテストコードを書かなきゃいけないのか？」なんて疑問が湧いてくるわけです。
自分もここめっちゃ混乱しました。
Seleniumテストスクリプトは、サーバーサイドとは全く関係ありません。


## 間違ってたら訂正よろしくおねがいしまーす
整理して書いてみましたが、間違っているかもしれません！
優しいご指摘をお願いします。