Selenium IDEの自動実行に関するメモ
Last modified: 2007/08/01 13:20:00
勤務先(電気通信大学 情報基盤センター)でActive!mail 2003の負荷テストを行うことになった。Macで利用可能な、webインタフェースへの入力を自動化するツールとしてFirefox + Selenium IDEが使えることは分かったものの、設定済みの入力手順を実行するにはGUIの実行ボタンをクリックする必要があり、センターの演習教室にある90台のiMacで一斉に負荷をかけるには不都合である。
「画面に描画されているピクセルのパターンを検索して、予め登録されたものと一致していたらクリックイベントを発生させる」という手法も存在する(参考文献失念…)。これは一般性も高く有用だが、今回は実装が間に合いそうになかった。一方で、Apple Remote Desktop(ARD)を利用すればアプリケーションの一斉起動は可能である(「UNIXコマンドを送信」を使って open /Applications/Firefox.app を送信すればよい)。そこで、Firefox起動時にSelenium IDEの実行を発火する方法を検討した。
当初は、Selenium IDEの実行ボタンに割り当てられたJavaScript関数を何らかの方法でキックすればよいだけなのですぐにできると思っていたが、思ったよりは面倒だった。想定された問題点と解決方法は以下の通り。
第2点について、本来のSelenium IDEでは、Firefoxがファイルのアップロード時などに表示する選択ウィンドウを介してファイルを選択するようにできている。この関数をそのまま使ってもGUI操作が必要になってしまうので意味がない。そこでファイル名を決めうちにしてそれを読み込ませることにした(全端末の特定のパスにファイルを配置するのはARDで簡単にできる)。
第3点は、Selenium IDEが起動されるときに呼び出される関数の終わりに仕込みを入れればよい。該当の関数はselenium-ide-sidebar.xulのonload="new Editor(window, true)"から、Editor()であることが分かる。最終的にSelenium IDEに仕込んだコードは以下の通り(diff -c形式)。
*** editor.js.0 Tue Jul 24 02:05:55 2007 --- editor.js Tue Jul 24 03:12:35 2007 *************** *** 66,71 **** --- 66,78 ---- if (isSidebar) { Recorder.registerForWindow(window.parent, this); + // by kazutaka + var testSeq = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); + testSeq.initWithPath("/tmp"); + testSeq.append("seleniumtest"); + var testCase = this.currentFormat.loadFile(testSeq, false); + this.setTestCase(testCase); + this.selDebugger.start(); } else { Recorder.registerAll(this); }
まず、実行手順が保存されたファイルを開くためにnsILocalFileのインスタンスを得る。このあたりはCode snippets:File I/O - MDCに詳しい。ここでは実行手順のファイルを/tmp/seleniumtestというファイル名で用意することにしたので、そのパスを設定する。あとはeditor.js, format.js, testCase.jsなどを参考にしながら、ファイルから読み込んで、それを現在のテストケースに設定して、実行ボタンを発火する、という処理を順に記述する。
変更したeditor.jsを含むselenium-ide.jarを作り直して配置し、Macの場合はそのユーザの ~/Library/Application Support/Firefox をコピーしてやれば、他のユーザでも同じ設定で動作させることができる。Linuxなどでも恐らく同様。
なお、一斉起動したFirefoxはARDで killall firefox-bin を送信すれば一斉に停止させられるが、次回起動時にセッションマネージャのポップアップが出てきてしまう。前述のコピーの前に、about:configでbrowser.sessionstore.resume_from_crashをfalseに切り替えておくとよい。もちろん、prefs.jsを手で書き換えても構わない。