selenium web driver で入力フォームテストをするときにハマりどころ

# selenium web driver で入力フォームテストをするときにハマりどころ

入力フォームのテストをする機会があり、前から気になっていたseleniumを試してみることにしました。初めて使ってみてハマったところをメモしておきます。


## 環境
ActivePerl v5.16.3
Selenium::Remote::Driver 0.2102
Selenium::Remote::WebElement　0.2202
selenium-server-standalone-2.44.0.jar

## 入力ボックスに正しく入力できないときがある。
テキストボックスなどに`send_keys`して値を設定しても、タイミングの問題なんかで正しく設定できない場合があります。しかも、エラーも吐かないから失敗したことがわからない。なので入力ボックスの値を監視しつつ、正しく値が設定されるまで何度も`send_keys`するようにしました。

```
my $value;	# 設定した値
my $webelement = $driver->find_element($element, $scheme);
until( $webelement->get_value eq $value ){
	$webelement->clear;
	sleep(0.01);
	
	$webelement->send_keys($value);
	sleep 0.1;
}
```


## リンクをクリックしてもページ遷移が行えないときがある。
リンクをクリックしてもページ遷移が行われない場合がありました。またページ遷移できてもリダイレクトされるページだとリダイレクト元のページでページ読み込み完了と判断されてしまい、期待したとおり動作しないことがありました。ページのソースを監視しつつ、waitをかけることで問題を回避できました。URLを監視したり、DOM要素を監視したりもしましたが、ソースを監視するのが一番うまく動きました。

```
my $monitoring_word = qr/word/;	# ページ遷移先にしかない適当なキーワード
until( $driver->get_page_source =~ $monitoring_word ){
	$driver->find_element($element, $scheme)->click;
	sleep 1;
}
```


## セレクトボックスの値が取得できない。
テキストボックスの場合はSelenium::Remote::WebElementのget_valueで入力値が取得できるけれど、セレクトボックスの場合は取得できませんでした。javascriptを使えば取得することができました。

```
# script to get the value of select boxses
my $script = q{
	var selectbox_id = arguments[0];
	var select = document.getElementById( selectbox_id );
	
	var val = select.options[select.selectedIndex].value;
	var txt = select.options[select.selectedIndex].text;
	return txt;
};

# get the value of select box
my $selectbox_value = $driver->execute_script($script, $selectbox_id)

```


## ブラウザの読み込みが完了しない。
読み込みが完了しないのか、なんなのか理由は分からないけど、URL読み込みをしても次の処理が始まらないことがありました。おそらくサイトの作りに原因があるんだろうけど。今回はFirefoxだと処理が止まってしまったけどChromeでは問題なく進んだのでChromeでテストをしました。


## ブラウザを使いまわすことによる副作用。
ブラウザの初回起動に８～１０秒くらいかかるので、時間短縮のために最初はブラウザを使いまわしてテストをしてました。ところが、ブラウザを使いまわすとページ読み込みが完了せず、次の処理に進めないという事象がおこりました。テスト対象が他サイトとも連携する構成だったのだけど、外部サイトからのレスポンスが帰ってきていない感じです。シューティングに時間が掛かりそうだったので、多少時間がかかるけど、都度ブラウザを起動し直すことにしました。


## エラーが発生するたびにテストが中断される。
これはseleniumに全く関係がないのだけど、色々工夫しても想定外のエラーや一過性のエラーでテストが止まってしまうことが度々ありました。テストを実行させて３時間放置させて戻ってきたら、最初の３０分でテストがコケてたとか、ほんと泣きそうになります。ある程度動作するテストがかけたら、しっかり例外処理して、テストが止まらないようにしたほうが、トータルのテスト時間を短くできたかなと反省しました。


## 複雑な要素のDOMアクセスが面倒。
`find_element`、`find_child_element`を使えば大体のDOMアクセスは可能ですが、複雑な条件のDOMアクセスには不便だと感じました。その場合、他のモジュールでDOMアクセスしてからWebDriverに操作対象のDOMを渡すと楽ちんできます。今回はHTML::TreeBuilderを使いました。

```
# ブラウザに読み込まれているHTMLソースをparse
my $tree = HTML::TreeBuilder->new; # empty tree
$tree->parse( $driver->get_page_source );

# 好きなようにDOMアクセスし、対象のIDを取得
my $id = $tree->find('...');

# IDを使って$driver経由でDOMアクセス
$driver->find_element($id, 'id');
```

[HTML::TreeBuilderの使い方](http://www.virment.com/programming/1702/)


## 未解決な問題
セレクトボックスに値を設定しようとしてもひっかかって？設定できないことが稀に起こりました。セレクトボックスの選択肢が以下のとおりだったとして、１月１１日をセットしたいのに画面上は１月１０日で止まってしまう、ような動作でした。仕方がないので、その度に手で目的の値を設定して処理をつづけました。

■選択肢
１月０９日
１月１０日　←ここ引っかかる
１月１１日　←この値を設定したい
１月１２日



## 参考文献

[Selenium::Remote::Driver](http://search.cpan.org/~gempesaw/Selenium-Remote-Driver-0.2202/lib/Selenium/Remote/Driver.pm#quit)
[Selenium::Remote::WebElement](http://search.cpan.org/~aivaturi/Selenium-Remote-Driver-0.15/lib/Selenium/Remote/WebElement.pm#send_keys)
[全国のSeleniumer必読](http://qiita.com/oh_rusty_nail/items/b8ba525d31ea7c522856)