【社内勉強会】Seleniumの紹介(2017/08/09) 


# はじめに


--------------------
## 注意事項
* 私は、Seleniumを使ってテストコードは書いていません。

## 前提知識
* HTMLの基礎
* CSSセレクタ

--------------------
## 参考図書

![Selenium実践入門.jpg](https://qiita-image-store.s3.amazonaws.com/0/37903/4b07b308-4044-fcab-b13d-30526945ff8f.jpeg)

[『Selenium実践入門』技術評論社](http://gihyo.jp/book/2016/978-4-7741-7894-3)

--------------------
## 目次
1. Seleniumの概要
2. Sleniumを動かしてみる
3. Seleniumでできること
4. Selenium IDE


--------------------
# 1. Seleniumの概要

--------------------
## Seleniumとは
* Webアプリケーションの画面操作を自動化するツール。
* 主に画面テストの自動化に使われる
* テスト以外にも使われる
    - 大量のデータの登録などの単純作業
    - Webスクレイピング

 >Selenium automates browsers. That's it!

※ http://www.seleniumhq.org/ 引用
 
 --------------------
## Seleniumを構成する主なツール
Seleniumはツールの集合体。単体のツールではない。

* Selenium WebDriver（以下、WebDriver)
    - Java, Ruby, JavaScriptなどのプログラミング言語から、ブラウザ操作が可能
    - 本格的なテスト自動化に適している
    (コードの共通化などによるメンテナンスコスト削減が可能なので)

* Selenium IDE
    - ブラウザ操作を記録して再生できるFirefoxのアドオン
    - Seleniumの体験に適している
    - 本格的な運用には適していない

※ [Selenium Project](http://www.seleniumhq.org/projects/) 引用

--------------------
## Seleniumがサポートしている主なプラットフォーム

* ブラウザ
    - Firefox
    - Chrome
    - Internet Explore
    - Microsoft Edge
    - PhantomJS(後述)
* OS
    - WIndows
    - Mac OS X
    - Linux
* プログラミング言語
    - Java
    - C#
    - Python
    - JavaScript
    - Python
    - Ruby

※ [Platforms Supported by Selenium](http://www.seleniumhq.org/about/platforms.jsp#testing-frameworks) 参考


--------------------
# 2. Seleniumを動かしてみる

--------------------
## テスト対象のサイト

```html
<input type="text" id="inputX"> ＋ <input type="text" id="inputY">
＝ <input type="text" id="result" readonly>
<br>
<button type="button" id="calculate" onclick="calculate();">Calculate</button>
```

```js
function calculate() {
  var result = Number(document.getElementById("inputX").value) + Number(document.getElementById("inputY").value);
  document.getElementById("result").value = result;
}
```

--------------------
## 実行環境の構築

* Selenium 3.4.0
* JUnit 4.12
* Firefox 54.0
* [geckodriver v0.18.0 ](https://github.com/mozilla/geckodriver/releases)
    - Firefox用のドライバ
    - exeファイルを適当のフォルダに配置


```xml:pom.xml
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.4.0</version>
    </dependency>
</dependencies>
```

--------------------
## Seleniumを使ったテストコード

```java:SampleTest.java
public class SampleTest {
	WebDriver driver;

	@Before
	public void setUp() throws Exception{
		//geckodriver.exeのパスを設定
	    System.setProperty("webdriver.gecko.driver", "/tmp/geckodriver.exe");
	    //Firefox起動
	    driver  = new FirefoxDriver();
	    //画面遷移
	    driver.get("file:///C:/tmp/sample.html");
	}

	@Test
	public void 入力値が1と2のときの加算結果が表示される() {
		//テキストボックスに"1"を入力する
		WebElement xElm = driver.findElement(By.id("inputX"));
		xElm.clear();
		xElm.sendKeys("1");
		//テキストボックスに"2"を入力する
		WebElement yElm = driver.findElement(By.id("inputY"));
		yElm.clear();
		yElm.sendKeys("2");
		//ボタンを押す
		driver.findElement(By.id("calculate")).click();

		//計算結果用のテキストボックスのvalue属性値を取得
		String actual = driver.findElement(By.id("result")).getAttribute("value");
		String expected = "3";
		//期待結果の比較
		assertThat(actual, is(expected));
	}

	@After
	public void tearDown() throws Exception{
		driver.quit();
	}
}
```


--------------------
# 3. Seleniumでできること

--------------------
## Selenium WebDriverの仕組み

![selenium 仕組み.png](https://qiita-image-store.s3.amazonaws.com/0/37903/45cf0425-de96-0cf0-eb51-25ceb5022434.png)
※ https://app.codegrid.net/entry/selenium-1 引用


--------------------
## WebDriverでできること part1
* 要素の取得
    - ID属性の値
    - CSSセレクタ記法
    - XPath記法
* 要素の操作
    - URL遷移
    - クリック
    - キー入力
    - チェックボックス、ラジオボタン、プルダウンの選択
    - subnit
* 要素情報の取得
    - 表示・非表示
    - 有効・無効
    - 存在するかどうか
    - 選択状態
    - 属性、テキスト、タグ名
    - CSSプロパティ
    - サイズ、位置
* ブラウザ情報の取得
    - タイトル、URL
    - HTMLソース
    - ウィンドウ位置、ウィンドウサイズ
    - Cookie    

※ 『Selenium 実践入門』4.3～4.6章 参考
※ [Selenium Web Driver](http://www.seleniumhq.org/docs/03_webdriver.jsp) 参考

--------------------
## WebDriverでできること part2

* 画面キャプチャ
    - ブラウザの種類によって、スクロール範囲外が含まれるかどうかが変わる
    ※ [Seleniumのスクリーンショットはどうやって撮っているのだろう](http://qiita.com/gluelan2013/items/496acff46b4c257c3ad0) 参照
* JavaScriptの実行
* ブラウザの戻る、進む
* 待ち処理
* Alert, Cnfirm, Promptダイアログの操作
    - Safari, PahntomJsのドライバでは操作できないらしい(未確認)
    - ダイアログが表示された状態の画面キャプチャは取得できない
* ウィンドウの操作
* フレームの操作
* マウス・キーボード操作
    - ダブルクリック、右クリック
    - マウスの移動、ドラッグ＆ドロップ
    - キーを押しながらクリック

※ 『Selenium 実践入門』4.7～4.10章 参考

--------------------
## WebDriverでできないけど、工夫すればなんとかできること

* ファイルアップロードダイアログ
    - ダイアログを直接操作できない
    - 対応案： input要素に`sendKey`メソッドで直接パスを入力する

* ファイルダウンロード
    - ダイアログを直接操作できない
    - 対応案1：ブラウザ設定で、ダウンロードダイアログを非表示にする
    - 対応案2：ブラウザ設定で、ダウンロードディレクトリを指定する
    -  InternetExploreDirverでは確認ダイアログを非表示にできない(未確認)

* 新しいtypeのinput要素(HTML5から導入）
    - typeが日付・時刻
    - typeがrange
    - typeがcolor
    - 対応案：JavaScriptでvalue属性の値を設定する

※ 『Selenium 実践入門』5章 参考

--------------------
### [私見] WebDriverのできる/できないの勘所

* JavaScriptができることは、WebDriverもできる
* ブラウザごとに動きやレイアウトが異なる機能は、できない場合がある
    - ダイアログなど
* セキュリティの観点で制限がある機能は、できない場合がある
    - ファイル操作
    
--------------------
# 4. Selenium IDE


--------------------
## [Try] Selenium IDEの操作
* 記録の開始
* テストの再生
    - 速度調整
* テストケースの保存
    - HTMLファイル
* プログラミング言語へのエクスポート

--------------------
## Selenium IDEの特徴
* ブラウザ操作を記録して再生できるFirefoxのアドオン
* テストコードがHTMLファイルのため自由度が低い
    - if文やfor文が書きにくい（書くことは可能）
* 古いSeleniumがベースになっているので、WebDriverよりできることが少ない

--------------------
### [補足] Selenium Builder
* Selenium IDEの後継ツール
* WebDriverをベースにしているので、Selenium IDEよりできることが多い
* Selenium IDEより使いづらい
    - [徹底比較！Selenium Builder vs Selenium IDE - Part 1](p://blog.trident-qa.com/2013/12/selenium-builder-vs-ide-1/)参照


--------------------
## Selenium IDEの要素取得(locator)

* locatorの優先度(ID, css, xpathなど)は、設定で変更できる
* ID属性がない要素のlocatorは読みにくい
* たとえば、以下のボタン操作を記録した場合、2個目のボタンはXPATHを使ったlocatorになる
   
```html
<!-- locaitor: css="button.sample" -->
<button class="sample" >sample</button>
<!-- locator: css="button.sample" -->
<button class="sample" >sample</button>
```
--------------------
## [私見] Selenium IDEでテスト自動化を行うべきか？

* Selenium IDEのコード(HTMLファイル)で自動化するのは、非現実的
   - 共通化が難しい
   - クロスブラウザテストが難しい(できなくはなない）
* Selenium IDEのコードからエクスポートしたWebDriverのコードで、テスト自動化した方がよさそう。上記の問題は解決できる。

* 間違った操作も記録されるが、それを修正するのが面倒。

* WebDriverに慣れたら、Selenium IDEで記録するより、直接WebDriverでコードを書いた方が、生産性が良さそう








--------------------------
# 付録

-----------
## ページオブジェクトパターン

* メンテナンス性の高いコードを作成する共通化技法
* テスト対象の画面情報を共通クラスに集約
    - 画面構成の修正に伴う修正コストを削減

-----------
### ページオブジェクトパターンのサンプル

* 以下のソースはページオブジェクトパターンで書いたコード。たとえば、ボタンのID属性値"calculate"が変わっても、テストコードは1か所を変えるだけでよい。

```java:CalculatePage.java
public class CalculatePage {
	private WebDriver driver;

	public CalculatePage(WebDriver driver) {
		this.driver = driver;
	}

	/** 計算ボタン */
	@FindBy(id = "calculate")
	private WebElement calculateButton;

	/** 計算ボタンを押す */
	public void calculate() {
		calculateButton.click();
	}
}
```


--------------------
## Selenium関連のライブラリ

WebDriverのコマンドは冗長

* Geb
    - Groovy言語(Java言語の拡張)で簡潔に記述できる
    - jQuery記法に近い記述で、要素を取得できる
    
* Fluentlenium
    - Javaで簡潔に記述できる
    - jQuery記法に近い記述で、要素を取得できる
    - Page Object Patternを支援する機能を持つ

私はFluentleniumを使っている。

```java:FleuentleniumSample.java
//WebDriverの記述
driver.findElement(By.id("calculate")).click();
//Fluentleniumの記述
$("calculated").click();
```

---------
## PhantomJS

* ヘッダレスブラウザ
* UIを持たないブラウザ
* 高速に動作する

---------
## WebDriverはテスト用の機能がない

期待結果の検証はJunitを使っているが、JUnitでなくてもよい。


--------------------
## テスト自動化の参考サイト

* [テスト自動化の現場から～落とし穴に気を付けよう～](https://www.slideshare.net/maycebook/ss-53516720)

* [Seleniumアレルギーのための処方箋](http://qiita.com/cognitom/items/27b7375bea653b414c8f)



------------------
##  Selenium以外のWebテストツール

* [List of web testing tools (Wikipedia)](https://en.wikipedia.org/wiki/List_of_web_testing_tools)

* [ブラウザテストツール総まとめ・2016年夏版](http://qiita.com/cognitom/items/6cce719b57341769c14d)

### 他のツールと比較したSeleniumの特徴
* 無料でオープンソース
    - [Ranorex 価格](https://www.techmatrix.co.jp/product/ranorex/price.html)
    - [TestComplete 価格](https://www.xlsoft.com/jp/products/smartbear/price.html)
* サポートしているブラウザが多い


------------------
### その他の感想

* IE実行の環境設定が面倒。そしてハマりやすい。
    - レジストリの設定が必要
    - ズームを100%にしないとエラー
    - 「保護モード」を考慮する必要あり
    - [SeleniumでInternet Explorer11を動かす方法](http://bitwave.showcase-tv.com/selenium%E3%81%A7internet-explorer11%E3%82%92%E5%8B%95%E3%81%8B%E3%81%99%E6%96%B9%E6%B3%95/)　参考


---------
#  Seleniumを使う際の工夫

* 要素の取得や結果の比較には、できるだけ変更されにくい値（IDやname属性値など）をを、参照すること

* 「JavaScriptのエラーがないこと」を確認するのは簡単なので、テストコードに組み込んだ方がよさそう