Hatena::ブログ(Diary)

bonlife このページをアンテナに追加 RSSフィード

言及ISBN/ASIN
  • Ringo EXPO 08 [DVD]
  • 三文ゴシップ
  • my way
  • ビジネスパーソンのための話し方入門 (日経文庫)
  • ザ・グーグルウェイ グーグルを成功へ導いた型破りな戦略
  • 考え・書き・話す3つの魔法
  • 自分の答えのつくりかた―INDEPENDENT MIND

2008-02-13 寒くて死にそうです。

Selenium IDEで1つ1つのテストの処理時間を計測 (悪戦苦闘)

bonlifeです。Oracleの設定変更するとかなんとかで、Webアプリケーションテストをちょっとだけ担当することになったので、Selenium使ってみました。普通はサーバデプロイ(って単語がなんか強そう!)して使うと噂のSelenium。諸事情あってサーバには導入し辛いので、Firefoxの拡張として使えるSelenium IDEで頑張ってみましたよ。

Automating Selenium IDE tests - Selenium IDE - Confluence」あたりを参考にして色々と試して感動!!でも、なんだかテストのログの残し方がよく分からない…。[Show Log]とかしておけば画面にログが出るので、それをコピーすれば良いかな、と最初は思ってたのですが、store*した変数の値とかまで出力されるわけじゃないっぽいので、なんかちょっと違う感じ。このあたりに詳しそうな人もまわりにいなかったので、悪戦苦闘しまくりながら、自分でなんとかしてみました…。

今回はOracleの設定変更で処理速度が低下していないことを確認したいので、時間計測が超重要。(Oracle 11gだったらそういうのに持ってこい!な「Real Application Testing」があるんですよね、確か。) 処理開始時のDate()をstoreEvalでstart_timeって名前付けて取っておいて、処理後のDate()の結果(end_time)との差を出せば、処理時間GETだぜ作戦。(なんかマニュアルをもっとちゃんと読めば書いてありそうですけどね…。TestSuite全体の処理時間ブラウザにも表示されますが、1つ1つのテストの処理時間については載ってなかった気がします。)

以下がテストケースの例。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>case01</title>
</script>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">case01</td></tr>
</thead><tbody>
<tr>
	<td>storeEval</td>
	<td>new Date().getTime()</td>
	<td>start_time</td>
</tr>
<tr>
	<td>open</td>
	<td>/cgi-bin/hoge.cgi</td>
	<td></td>
</tr>
<!-- 中略 (ここでテキストフィールドに値を設定したり) -->
<tr>
	<td>clickAndWait</td>
	<td>search</td>
	<td></td>
</tr>
<tr>
	<td>assertText</td>
	<td>xpath=/html/body/table[2]/tbody/tr/td/p/text()</td>
	<td>hogehoge</td>
</tr>
<tr>
	<td>storeEval</td>
	<td>new Date().getTime()</td>
	<td>end_time</td>
</tr>
<tr>
	<td>storeEval</td>
	<td>Math.round((storedVars['end_time'] - storedVars['start_time']) / 1000)</td>
	<td>elapsed_time</td>
</tr>
<tr>
	<td>storeEval</td>
	<td>doWriteResult('case01', storedVars['elapsed_time'])</td>
	<td>dummy</td>
</tr>
</tbody></table>
</body>
</html>

処理時間を取得しても、どこかに残しておかないとアレなので、今回はファイルに書き込むことにしました。それが上の doWriteResult('case01', storedVars['elapsed_time']) の部分。JavaScript変数スコープとかもよく分かってないでアレですが、1つのテストの結果を変数に格納しておいて次のテストで使ったりするのが私には難しかったので独自に関数を定義して、ファイル書き出しですよ。

以下のように doWriteResult() を定義しています。JavaScriptでのローカルファイルの操作が思いのほか難しくて死ぬかと思いました。が、TiddlyWikiソースコードを(丸々)参考にしてなんとかでっち上げましたよ! (なんとなく do で始まる関数が良いんだぜ、敵な箇所がマニュアルにあったので、そこを真似したり失敗してる内に変な関数名になってしまいましたが、ご愛嬌。Selenium.prototypeを拡張する場合だったかな。よくワカリマセン…。)

  • output_elapsed_time.js
doWriteResult = function(testcase_number, elapsed_time) {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
    var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
    today = new Date();
    yyyy  = today.getFullYear();
    mm    = today.getMonth() + 1;
    dd    = today.getDate();
    if ( mm < 10 ) { mm = "0" + mm; }
    if ( dd < 10 ) { dd = "0" + dd; }
    today_YYYYMMDD = yyyy.toString() + mm.toString() + dd.toString();
    file.initWithPath("C:\\selenium\\test\\elapsed_time_" + today_YYYYMMDD + ".txt");
    if(!file.exists()) { file.create(0,0664); }
    var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
    out.init(file,0x02 | 0x10,0664,null);
    elapsed = testcase_number + "\t" + elapsed_time + "\n";
    out.write(elapsed, elapsed.length);
    out.flush();
    out.close();
};

用途は限られているのでフォルダのパスは固定。日をまたがってテストをすることもなさそうなので、ファイル名には YYYYMMDD を付与。で、ブラウザURL欄に以下のような文字列をコピペして実行ですよ。

chrome://selenium-ide/content/selenium/TestRunner.html?baseURL=http://www.example.com/&test=file:///C:/selenium/test/test_suite.html&userExtensionsURL=file:///C:/selenium/test/output_elapsed_time.js

う、動きました…。ファイルに処理時間(秒)がたんたんと記録されました。妙な達成感ですよ!!でも、でもでも。本当は user-extensions.js とかで拡張したり、なんかもうちょっとマシなやり方があると思うのですが、どうでしょう。教えてエロイ人!! (なんだか激しく勘違いをしていそうな予感です。)

トラックバック - http://d.hatena.ne.jp/bonlife/20080213/1202913177