SeleniumIDEでテストスクリプトを作ってみる

# お題目
テストスクリプト作成では　スクリプト設計　と　テスト設計の両方の検討が必要です

# 前提
環境としてSeleniumIDEがインストールされていること
また、SeleniumIDEで使用できるプラグインは今回使用しません。

## テストサンプル画面について
今回は　日本Seleniumユーザーコミュニティ（https://groups.google.com/forum/#!forum/seleniumjp） で作成された　デモ用サイトを利用させてもらいます

>宿泊予約システム
http://example.selenium.jp/reserveApp/
>

###  基本仕様
宿泊開始日は　翌日以降
予約可能期間は　３か月以内
宿泊期間は　１～９日まで
宿泊人数は　１～９人まで
宿泊料　平日　７０００円
　　　　土日　２５％増し
朝食バイキング　　　一人あたり　１０００円増し
昼からチェックイン　一人あたり　１０００円増し
お得な観光プラン　　一人あたり　１０００円増し
名前　半角50文字


# テスト設計
分け方については、いろいろコメントで突っ込んでください
(JSTQBシラバス未確認）

## 正常系
- 表示チェック（静的）
- 表示チェック（動的）
- 計算ロジックチェック
- 遷移チェック

## 準正常系
- バリデーションチェック

## 異常系
- 今回は対象外

## シナリオ
- 項目組み合わせ（全項）
- 項目組み合わせ（２項間）


# スクリプト設計
基本的に、予約画面で値を入力し、予約完了画面で結果が表示される流れです

初めの一歩は　リニアスクリプト

テスト対象画面を表示し、できる操作を行って、ロケーションが正しく指定できるかを確認


## 正常系の表示

```
<tr>
	<td>open</td>
	<td>http://example.selenium.jp/reserveApp/</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_year</td>
	<td>2015</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_month</td>
	<td>7</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_day</td>
	<td>2</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_term</td>
	<td>3</td>
</tr>
<tr>
	<td>type</td>
	<td>id=headcount</td>
	<td>1</td>
</tr>
<tr>
	<td>click</td>
	<td>id=breakfast_on</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=plan_a</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=plan_b</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=guestname</td>
	<td>瀬簾　爾績</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=goto_next</td>
	<td></td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=price</td>
	<td>27700</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=datefrom</td>
	<td>2015年7月2日</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=dateto</td>
	<td>2015年7月5日</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=headcount</td>
	<td>ご人数: 1名様</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=bf_order</td>
	<td>あり</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=gname</td>
	<td>瀬簾　爾績</td>
</tr>
```

一般的な値を入れて普通に表示されていることを確認しています

ちなみにHTML的には見事に　IDが設定されています
が、実際にはまったくなかったり、動的に付与されていたりで最も苦労するところのはず


## 準正常系
エラーメッセージ処理でエラーメッセージが表示される場所のロケーションも確認

```
<tr>
	<td>open</td>
	<td>http://example.selenium.jp/reserveApp/</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_year</td>
	<td>2014</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_month</td>
	<td>7</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_day</td>
	<td>2</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_term</td>
	<td>3</td>
</tr>
<tr>
	<td>type</td>
	<td>id=headcount</td>
	<td>1</td>
</tr>
<tr>
	<td>click</td>
	<td>id=breakfast_on</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=plan_a</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=plan_b</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=guestname</td>
	<td>瀬簾　爾績</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=goto_next</td>
	<td></td>
</tr>
<tr>
	<td>assertText</td>
	<td>id=errorcheck_result</td>
	<td>宿泊日には、翌日以降の日付を指定してください。</td>
</tr>
```

バリデーションエラーの場合メッセージが

```
年月日、期間、人数いずれかの値が半角英数の範囲外です
```

に変わります

## 考察
リニアスクリプトでテストケースを作っていくと以下のバリエーションでスクリプトをどんどん増やしていくことになります

- 入力値の変更
- 入力値に合わせた検証値の変更

この方向に進むと テストパターン分スクリプトを作ることになるため実行スクリプトが爆発的に増加してしまいます
また、画面構造に変更があった場合、全スクリプトを修正することになります　
 
これを回避するためには以下が考えられます

- テストデータの変数化
- ロケーション指定の抽象化

## テストデータの変数化

入力値を可変にできるように変数を導入してみる


```
<tr>
	<td>open</td>
	<td>http://example.selenium.jp/reserveApp/</td>
	<td></td>
</tr>
<tr>
	<td>storeEval</td>
	<td>new Date().getFullYear()</td>
	<td>reserve_year</td>
</tr>
<tr>
	<td>storeEval</td>
	<td>new Date().getMonth()+1</td>
	<td>reserve_month</td>
</tr>
<tr>
	<td>storeEval</td>
	<td>new Date().getDay()+1</td>
	<td>reserve_day</td>
</tr>
<tr>
	<td>store</td>
	<td>1</td>
	<td>reserve_term</td>
</tr>
<tr>
	<td>store</td>
	<td>1</td>
	<td>headcount</td>
</tr>
<tr>
	<td>store</td>
	<td>瀬簾　爾績</td>
	<td>guestname</td>
</tr>
<tr>
	<td>getEval</td>
	<td>
var date1 = new Date([storedVars.reserve_year,storedVars.reserve_month,storedVars.reserve_day].join('/'));
date1.setDate(date1.getDate()+Number(storedVars.reserve_term));
storedVars.reserve_e_year = date1.getFullYear();
storedVars.reserve_e_month = date1.getMonth()+1;
storedVars.reserve_e_day = date1.getDate();
        </td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_year</td>
	<td>${reserve_year}</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_month</td>
	<td>${reserve_month}</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_day</td>
	<td>${reserve_day}</td>
</tr>
<tr>
	<td>type</td>
	<td>id=reserve_term</td>
	<td>${reserve_term}</td>
</tr>
<tr>
	<td>type</td>
	<td>id=headcount</td>
	<td>${headcount}</td>
</tr>
<tr>
	<td>click</td>
	<td>id=breakfast_on</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=plan_a</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=plan_b</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=guestname</td>
	<td>${guestname}</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=goto_next</td>
	<td></td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=price</td>
	<td>10000</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=datefrom</td>
	<td>${reserve_year}年${reserve_month}月${reserve_day}日</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=dateto</td>
	<td>${reserve_e_year}年${reserve_e_month}月${reserve_e_day}日</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=headcount</td>
	<td>ご人数: ${headcount}名様</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=bf_order</td>
	<td>あり</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=plan_a_order</td>
	<td>昼からチェックインプラン*</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=plan_b_order</td>
	<td>お得な観光プラン</td>
</tr>
<tr>
	<td>verifyText</td>
	<td>id=gname</td>
	<td>${guestname}</td>
</tr>
```

## 考察

変数化によりテキストデータの変更はしやすくなったが、操作をおこなうチェックボックス、ラジオボタンについては　このままでは変数化が難しいことが分かります（テストデータによって操作をしない　というスクリプトを組むには制御構文が必要になります）

なお、テストデータの設定方法はテスト設計で洗い出したケース数に合わせて検討が必要ですが、これはまた別の機会に。


# P.S
この内容は　Selenium談話会 in Slack　で取り上げた内容と一部かぶっています

##Selenium談話会 in Slack とは

Slackを使った　Selenium関連の　オンライン勉強会です
https://seleniumjp.slack.com

### 参加方法

とても簡単です。
https://seleniumjp.herokuapp.com より登録すると招待メールが自動で届きます。
（なお、ページを開くときに　サーバ側のインスタンス作成が動き出す関係上表示されるまで少しお待ちください。。。 :sweat_smile: