WebDriverの更新はWebdriverManagerに任せよう

この記事は[Selenium/Appium Advent Calendar 2017](https://qiita.com/advent-calendar/2017/selenium)の4日目です。

3日目とネタが被って焦りましたが💦  、[WebdriverMangar](https://github.com/bonigarcia/webdrivermanager-examples)について書いていきたいと思います。

### 使用するきっかけ

2017年某日、ある日突然テストが動かなくなりました。
散々悩んだ挙句、別チームの人に教えてもらってChromeのバージョンアップ後にWebDriverを更新してないせいだと分かりました。
これは面倒だなと思っていたところ、Selenide4.7のリリースノートで、最新のWebdriverを自動的にダウンロードしてくれるWebdriverManagerを知り早速使い始めました。

### WebdriverManagerの使い方

Selenideは内包しているので、生で使う場合のコードを例にあげます。

```java
@Test
public void test() {
    // WebdriverManagerの処理は実質これだけ
    ChromeDriverManager.getInstance().setup();

    // 実行するとWebdriverのパスをシステムプロパティ設定してくれている
    String driverPath = System.getProperty("webdriver.chrome.driver");
    System.out.println(driverPath); // ~/.m2/repository/webdriver/chromedriver/mac64/2.33/chromedriver

    // あとは普通にテストを書くだけ
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("http://www.google.com/");

    WebElement element = webDriver.findElement(By.name("q"));
    element.sendKeys("Selenium/Appium Advent Calendar 2017");
    element.submit();

    System.out.println(webDriver.getTitle());

    webDriver.quit();
}
```

XXXDriverManagerクラスを生成してsetupメソッドを呼ぶと、最新のWebdriverをダウンロードしてくれる仕組みです。
Webdriverのパスを、ブラウザに応じたシステムプロパティに設定してくれるのであとは好きにテストを書くだけです。


### 対応しているブラウザ

- Chrome
- Firefox
- Opera
- PhantomJS
- Edge
- IE

### 最新のバージョンを使いたくない場合

最新のWebdriverを使うと逆に困るようなケースでは、以下のようにしてバージョンを固定できます。

```java
// 最新を探しにいかない
ChromeDriverManager.getInstance().forceCache().setup();

// バージョン指定
ChromeDriverManager.getInstance().version("2.32").setup();
```

Selenideの場合は上記のように書けないので、システムプロパティ経由で設定します。

```java
@Test
public void test() {
    // システムプロパティに設定
    System.setProperty("wdm.chromeDriverVersion", "2.32");

    Configuration.browser = WebDriverRunner.CHROME;
    open("http://www.google.com/");

    String driverPath = System.getProperty("webdriver.chrome.driver");
    System.out.println(driverPath);

    $(By.name("q")).val("Appium Advent Calendar 2017").submit();

    System.out.println(Selenide.title());
}
```

### Selenium Gridで使う場合

現場ではまだ使っていないのですが、Nodeの起動前にsetupを呼べば良いはずです。
テストした下記のコードはごちゃ混ぜに書いているので分かりにくいですが、実際はHubの起動、Nodeの起動、テスト実行は別々に実行すると思ってください。。。
実際に使うときにはNodeを定期的に再起動するか、setupを呼ぶプログラムを定期的に実行するなどして最新を取得する実装が必要です。

```java
@Before
public void setup() throws Exception {
    // Setup Chrome webdriver
    ChromeDriverManager.getInstance().setup();
    String driverPath = System.getProperty("webdriver.chrome.driver");
    System.out.println(driverPath);

    // Start hub
    GridLauncherV3.main(new String[]{"-port", "4444"});
    // Start node
    GridLauncherV3.main(new String[]{"-port", "5555",
            "-role", "node",
            "-hub", "http://localhost:4444/grid/register"
    });

    Configuration.remote = "http://localhost:4444/wd/hub";
    Configuration.browser = WebDriverRunner.CHROME;
}

@Test
public void test() {
    open("http://www.google.com/");
    $(By.name("q")).val("Appium Advent Calendar 2017").submit();
    System.out.println(title());
}

@After
public void tearDown() {
    close();
}
```

### まとめ

とりあえずローカルPCでテスト実行では、Webdriverのバージョンを意識しなくてよくなりました。
また、Windows、Macなど実行環境別のWebdriverを管理する必要がないのも良いですね。
Selenium Grid環境にはまだ導入できてませんが、台数があるので導入すれば効果が高そうです。
という訳でWebDriverの更新はWebdriverManagerに任せましょう。