SeleniumIDE × SelBlocks活用事例

# はじめに
以前、 @____rina____ さんが書かれた記事[SeleniumIDE×SelBlocksを使ってXMLでDDT！](http://qiita.com/____rina____/items/245d22250426f289b841)を見てあとでやってみよう！
そして、やったらなんか気付きを書こうと思っていたので書きます！

# 事前準備
* 以下をインストールしてください
 * Firefox 
 * [Selenium IDE](https://addons.mozilla.org/ja/firefox/addon/selenium-ide/) (Firefoxアドオン)
 * [SelBlocks](https://addons.mozilla.org/ja/firefox/addon/selenium-ide-sel-blocks/) (Firefoxアドオン)

# これは使えるなと思ったコマンド
* forJson
 * テストデータをJsonファイルに集約し、ループ処理を行う
* if
 * getEvalコマンドでやっていた条件分岐を移行
 * getEvalコマンドでJavascriptが書けるがカオスになっていくし、みにくいのでツライ

# とあるテストをSelBlocksで改善した事例
* テストの中身には触れませんが、テストケース数は30 => 7 (ファイルサイズは1/3に)
 * この数字だけみてもコピーしてテスト作っていたことが想像できそうですよね

# 導入した結果変わったこと/気づいたこと
## 1. テストケースをコピーする文化がなくなった
* 例えば、環境毎で似たようなテストを実施するとき、URLが違うためテストケースをコピーでURLだけ修正していました
* 結果、中身はほとんど変わらないテストケースが複数ある　なんてことも

## 2. コードの保守性が向上した
* 今まではテストデータとテストそのものが同じファイルで管理していた
* Jsonファイルなどの別のファイルにテストデータを集約することで、テストデータの修正ならテストコードは見ることなくデータファイルの更新だけで済むようになった

## 3. コードの可読性が向上した
* Selenium IDEを使っているとgetEvalコマンドを使うシーンは多々ある
* このコマンドは便利でJavascriptがなんでもかけてしまうが、条件分岐や複雑な処理には向いておらず書けば書くほどみにくくなる
* 実際。自分が書いたコードでも少し経ってからみるとインプットするのに時間がかかることもありました(だれやこんなコード書いたのw)

## 4. データ更新を頻繁に行う必要が有る場合、外部ファイルにするのは変更が面倒！
* データの更新が頻繁に起こるという前提で話をしますが、
* 外部ファイルにテストデータを置くと変更はそのファイルだけで済みますが、毎回複数のxxxx.jsonのデータを変更しにいくのは面倒というのはありますね
* テストケースの変更であればSeleniumIDE上で修正ができるのに対し、外部ファイルにわけるとSeleniumIDE上での修正にならない>_<という
* 結果見たらその場でちょちょいと修正をいれたい　とそんな声もあるとおもいます

# SelBlocksで使えるようになるコマンドのサンプル集

#### if/else/elseIfコマンド

```:if_else_elseIf.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>if_else_elseIf</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">if_else_elseIf</td></tr>
</thead><tbody>
<tr>
	<td>foreach</td>
	<td>value</td>
	<td>'いちご', 'みかん', 'さくらんぼ'</td>
</tr>
<tr>
	<td>if</td>
	<td>value == 'いちご'</td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('いちごは400円です。');</td>
	<td></td>
</tr>
<tr>
	<td>elseIf</td>
	<td>value == 'みかん'</td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('みかんは150円です。');</td>
	<td></td>
</tr>
<tr>
	<td>else</td>
	<td></td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('${value}は時価です。');</td>
	<td></td>
</tr>
<tr>
	<td>endIf</td>
	<td></td>
	<td></td>
</tr>
<tr>
	<td>endForeach</td>
	<td></td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>
```

#### forコマンド

```:for.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>for</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">for</td></tr>
</thead><tbody>
<tr>
	<td>for</td>
	<td>i = 1; i <= 10; i++ </td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('試行回数：${i}');</td>
	<td></td>
</tr>
<tr>
	<td>endFor</td>
	<td></td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>
```

#### continue/breakコマンド

```:continue_break.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>continue_break</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">continue_break</td></tr>
</thead><tbody>
<tr>
	<td>for</td>
	<td>i = 1; i <= 100; i++ </td>
	<td></td>
</tr>
<tr>
	<td>break</td>
	<td>i == 10</td>
	<td></td>
</tr>
<tr>
	<td>continue</td>
	<td>i % 2 == 0</td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('${i}は奇数です');</td>
	<td></td>
</tr>
<tr>
	<td>endFor</td>
	<td></td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('終了');</td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>
```

#### forJsonコマンド

```:forJson.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>forJson</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">forJson</td></tr>
</thead><tbody>
<tr>
	<td>forJson</td>
	<td>price.json</td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('${value}は${price}円です。');</td>
	<td></td>
</tr>
<tr>
	<td>endForJson</td>
	<td></td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>
```

```:price.json
[
  { value: "いちご",     price: "400" },
  { value: "みかん",     price: "150" },
  { value: "さくらんぼ", price: "600" }
]
```

#### exitTestコマンド

```:exitTest.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>exitTest</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">exitTest</td></tr>
</thead><tbody>
<tr>
	<td>getEval</td>
	<td>LOG.info('このログは出力されます。');</td>
	<td></td>
</tr>
<tr>
	<td>exitTest</td>
	<td></td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('exitするためこのログは出力されません。');</td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>
```

#### call/functionコマンド

```:call_function.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>call_function</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">call_function</td></tr>
</thead><tbody>
<tr>
	<td>for</td>
	<td>i = 0; i <= 10; i++</td>
	<td></td>
</tr>
<tr>
	<td>call</td>
	<td>play</td>
	<td></td>
</tr>
<tr>
	<td>endFor</td>
	<td></td>
	<td></td>
</tr>
<tr>
	<td>function</td>
	<td>play</td>
	<td></td>
</tr>
<tr>
	<td>getEval</td>
	<td>LOG.info('試行回数：${i}');</td>
	<td></td>
</tr>
<tr>
	<td>endFunction</td>
	<td></td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>
```

----

# ～ただの宣伝～
* 最後まで読んでくださいましてありがとうございます。最後に宣伝をさせていただきます
* [全国のSeleniumer必読](http://qiita.com/oh_rusty_nail/items/b8ba525d31ea7c522856)
* Selenium, Appium, SauceLabs, TravisCI, Jenkinsに関するノウハウ書いているのでよかったら参考にしてみてください