今さらですがSeleniumをインストールしてみる

#ここへ至る経緯

今さらですが、WindowsでSelenium WebDriverを使ってみようと思ったのです。環境としては、Windows 10 64bit版とFirefox 50.0.2 32bit版、あとはCygwinと何か適当な言語があれば何とかなるだろうと。

。。。すいません、甘く見てました。

__Q. そもそも今までどうやって生きていたのかね君は。__
A. [MozRepl](https://addons.mozilla.org/ja/firefox/addon/mozrepl/)というのを使っていました。Firefoxでしか動かない実装ですが、[クライアント](https://github.com/bard/mozrepl/wiki#related-work)は各種そこそこ充実していまして、私はperlの[WWW::Mechanize::Firefox](http://search.cpan.org/perldoc?WWW%3A%3AMechanize%3A%3AFirefox)というのを使っていました。

理屈は単純で、FirefoxにMozReplアドオンをインストールして再起動し、 [ツール]→[MozRepl]→[Start] を選択すると、Firefoxがポート4242/tcpでLISTENします（このポート番号は設定で変えられます）。この状態で、例えば以下のようなプログラムを実行します。

```perl
use WWW::Mechanize::Firefox;
use utf8;

$mech = WWW::Mechanize::Firefox->new();
$mech->get("http://qiita.com/");
```

すると、タブが一つ開いて http://qiita.com/ が開きます。そこで、perl側からDOM構造にアクセスして読んだり書いたり``click()``したりと、いろいろ操作できます。とはいえ、Firefoxでしか動かないし、今どきperlだし、いつまでサポートが続くかわからないし、[バグ](https://rt.cpan.org/Public/Bug/Display.html?id=102649)はあるし、[バグ](https://rt.cpan.org/Public/Bug/Display.html?id=111579)はあるしで、そろそろ乗り移らないといかんなあと思ったのです。

#結論

Windows+Firefox+Seleniumの組み合わせは、現状かなり複雑なことになっています。今は過渡期なのかもしれないし、永遠にこんな調子なのかもしれませんが、意外とすんなり綺麗には行きません。それなりの根性を必要とします。

#何と何がどう組み合わさればSeleniumが成り立つのか

まずFirefoxを外部から操作するAPIについてですが、Selenium IDEがMozRepl機能拡張アドオンの代わりとして機能するわけではありません。

最近のFirefoxには、[Marionette](https://developer.mozilla.org/ja/docs/Mozilla/QA/Marionette)と称するAPIが内蔵されています。これを有効化するには、Firefoxに ``-marionette`` オプションをつけて起動します。

```
"C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -marionette
```

これで、Firefoxがポート番号2828/tcpでLISTENします。このポートに接続してコマンドを送り込むと、Firefoxを操作できます。ただし、ここで使われるプロトコルは「Marionetteプロトコル」であって、Seleniumとは互換性がありません（もちろんMozReplとも互換性はありません）。

そこで、Seleniumと互換性を取るために、Mozillaから[geckodriver](https://github.com/mozilla/geckodriver/releases)なるアプリケーションが提供されています。これはSeleniumプロトコルをMarionetteプロトコルに変換するサーバで、起動するとポート4444/tcpでLISTENします。

使い方としては、まずSelenium WebDriverを組み込んだテストコードを書きます。次にFirefoxを''-marionette''オプションつきで起動し、さらに先ほど書いたテストコードを起動します。

すると、テストコードの内部からSeleniumドライバはgeckodriverを起動し、4444/tcpに接続し、リクエストを出し、次にgeckodriverは2828/tcpでLISTENしているFirefoxに接続し、Marionetteプロトコルでリクエストを送るという順序です。

ここまでを表に整理すると、以下のようになります。

|テストコード||geckodriver||Firefox|
|--:|:-:|:--|:-:|:--|:-:|:--|
|プロセス起動||||''-marionette''オプションつきで起動|
|内部でgeckodriverを起動|→|プロセス起動||2828/tcpでLISTEN|
|||4444/tcpでLISTEN|||
|4444/tcpで接続|→||||
|「Selenium」プロトコルで送信|→|受信|||
|||2828/tcpで接続|→||
|||「Marionette」プロトコルで送信|→|受信|


そんなわけで、もしSeleniumが動かない状況に遭遇したら、2828/tcpが開いているか、4444/tcpが開いているか、geckodriver.exeが動いているか、といったところをチェックしてみて下さい。

__Q. で、結局何をインストールすればいいのか。__
A. Windows 10と[Firefox](https://www.mozilla.org/ja/firefox/new/)のほかに、[geckodriver v0.11.1 for Windows](https://github.com/mozilla/geckodriver/releases)が必要です。さらに、プログラミング言語ごとにドライバが必要です。

__Q. Selenium IDEはどこへ行ったのか__
A. MozReplと違い、SeleniumはFirefox側に拡張機能アドオンが何もなくても成り立ちます。機能拡張アドオンはあくまでテストコードの自動生成ツールです。テストを自分で手書きするなら、機能拡張アドオンは必要ありません。
ところで、[Selenium IDE](https://addons.mozilla.org/ja/firefox/addon/selenium-ide/)は既に旧世代化しており、今から使うには適しません。今から使うなら[Selenium Builder](https://addons.mozilla.org/ja/firefox/addon/selenium-builder/)が良いようです。

__Q. geckodriverは32bit版と64bit版があるが、どちらを選べばいいのか。__
A. geckodriverはTCPでlistenしてTCPでconnectするアプリですから、どちらでも構いません。Firefoxやプログラミング言語の実行環境に合わせる必要はありません。もちろん、OSが32bitなら32bitを選ぶ必要があります。

__Q. 多段でまだるっこしい。テストコードから直接Marionetteを呼び出すようにできないのか。__
A. 今のところ、これしかないようです。

__Q. Windows Firewallがうざい。__
A. ですよねー。

#プログラミング言語別ドライバ対応状況とサンプルプログラム

言語ごとのサポート状況はまちまちです。同じSeleniumといっても、言語ごとに呼び出し方がかなり大きく違いますし、処理系によってはSeleniumやFirefoxの更新について来られなくなって最新版に非対応という場合があるようです。

##Ruby
RubyGemsから[selenium-webdriver 3.0.3](https://rubygems.org/gems/selenium-webdriver)が入手できます。[RubyInstaller](https://rubyinstaller.org/)版ruby 2.3.3p222で動きました。しかし、[Cygwin](https://cygwin.com/) 64bit版 ruby 2.2.5p319では、どういうわけか動きませんでした。以下サンプルプログラムです。

```rb
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox
driver.get "http://qiita.com/"
```

##Perl
CPANを見ると、[WWW::Selenium](http://search.cpan.org/perldoc?WWW%3A%3ASelenium)というのがあることになっているのですが。。。

残念ながら、動きませんでした。最新版[Test-WWW-Selenium-1.36](http://search.cpan.org/~mattp/Test-WWW-Selenium-1.36/)の更新日付が2013年5月15日となっており、古いようです。

##Java
Maven Central Repositoryの[selenium-java 3.0.1](https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java/3.0.1)が正常に動くようです。以下サンプルプログラムです。``geckodriver.exe``の場所をシステムプロパティで指定しないとエラーになります。

```java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class SelenuimSample {

	public static void main(String[] args) {
		System.setProperty("webdriver.gecko.driver", "C:/cygwin64/usr/local/bin/geckodriver.exe");
		WebDriver driver = new FirefoxDriver();
		driver.get("http://qiita.com/");
	}

}
```

__Q. これは便利なのか不便なのかどうなのか。__
A. まあ、``CreateObject("InternetExplorer.Application")``の時代に比べればマシでは？

__Q. geckodriverは、geckoを搭載したブラウザであればFirefox以外でも動くのか。__
A. [Seamonkey 2.40](http://www.seamonkey-project.org/) に``-marionette``オプションをつけて起動してみましたが、ダメでした。

__Q. ところでPythonは？__
A. すいません忘れました。

以上！幸運を祈る。