こんにちは。出石です。
今回は自動テストのSeleniumを複数環境で実行できる「Selenium Grid」を試してみました。
一つのテストスクリプトを複数ブラウザで並行して実行できる為、ブラウザテストまたは実行時間の短縮になります。
環境準備
node環境については、当ブログの記事「サーバサイドJavaScriptのツール:Node.js Express.js MongoDB mongooseを使ってみる -インストール編-」を参考にしてください。
node、npmが使える環境であればサンプルプログラムを取得して頂くだけで準備は完了です。
$ git clone https://github.com/hatena-iti/SeleniumGridSample.git
実行を確認した環境は以下になります。
OS : windows7 64bit SP1 node : 0.10.35 npm : 1.4.28
また、使用したブラウザは以下になります。
GoogleChrome : 37 Firefox : 32 InternetExplorer : 11
以降、サンプルプログラムが取得された状態で説明していきます。
動作手順だけであればREADME.mdを参照ください。
利用モジュールのインストール
今回、並列実行する為のモジュールにwd-parallelを利用しました。
並列に実行する方法としては、他にJenkinsやCron(linux)などもありますが今回はDBやスレッド等の考慮は行わない前提で上記モジュールを利用しています。
インストールはpackage.jsonに設定していますので
$ npm install
だけです。
Grid hub、nodeの起動
Selenium Gridはnodeというブラウザ毎の環境を複数用意し、hubというGrid Serverが管理する構成をとります。
ですので、hub(server)とnode(client)をそれぞれ起動していきます。
※起動はそれぞれ別のコマンドプロンプトを開いて起動してください。
hubの起動は以下で行います。
$ setup_hub.cmd
setup_hub.cmdは次のコマンドを実行しています。
java -jar seleniumServer/selenium-server-standalone-2.43.1.jar -role hub
「-role hub」でSeleniumServerをhubとして起動するというコマンドです。
続いてnodeの起動は以下で行います。
$ setup_node.cmd
setup_node.cmdの内容は次の様になります。
java -jar seleniumServer/selenium-server-standalone-2.43.1.jar -role node -nodeConfig node.json -Dwebdriver.ie.driver=./webdriver/IEDriverServer32.exe -Dwebdriver.chrome.driver=./webdriver/chromedriver.exe
同じく「-role node」でnodeとして起動するコマンドです。
「-nodeConfig node.json」はブラウザ分の設定ファイルを指定しています。
それに続くオプションは、それぞれIEとChrome用のドライバの指定になります。FireFox用にドライバの指定はいりません。
IE用のドライバは32bit用と64bit用があり、今回は64bitを使おうとしたのですが 64bit用だとTextの入力処理が非常に重かったので、32bit用を使用しています。 しかし、32bit用だとTextの問題は解消される様ですがスクリーンショットが綺麗に撮れない問題もありました。
node.jsonは以下の設定としています。
{ "capabilities" : [ { "browserName": "firefox", "maxInstances": 2, "seleniumProtocol": "WebDriver" }, { "browserName": "chrome", "maxInstances": 2, "seleniumProtocol": "WebDriver" }, { "browserName": "internet explorer", "maxInstances": 2, "seleniumProtocol": "WebDriver" } ] , "configuration": { "hub": "http://localhost:4444/grid/register" } }
[capabilities]でnode(ブラウザ)の設定を行い、[configuration]でhubの指定をしています。hubは今回ローカルの設定としています。
nodeの設定にある[maxInstances]は使用できるインスタンスの数で、最大数を2としブラウザ毎に2インスタンス利用できる様に設定しています。
尚、今回利用するインスタンスはブラウザ毎に1つです。
hubとnodeが起動できたらブラウザからコンソールで確認ができます。
http://localhost:4444/grid/consoleを開くと以下の画面が表示され、設定したインスタンス等が確認できます。
それぞれのブラウザで2インスタンスが利用できる事が分かります。
ここまでで実行できる準備が整いました。
自動実行の並列起動
では、実際に並列起動を試してみたいと思います。
実行は
$ npm start
です。
実行するテストはparallel.jsになります。
var parallel_webdriver = require('wd-parallel'); var browsers = parallel_webdriver.remote(); // テストケース browsers.test = function(browser, target) { // 初期化 browser.init(target); // Windowのサイズを設定する browser.setWindowSize(640, 480, function(err) { }); // グーグルページを開く browser.get('http://google.com'); // 検索テキストに「Hello World」を入力 browser.elementByName('q').type("Hello World"); // 検索を実行 browser.elementByName('q').type("\n"); // 検索結果の画面に遷移するまで待つ(30秒) browser.waitForElementByCss('#hdtb_msb', 1000 * 30); // 画面のHCを撮る browser.saveScreenshot('results\\' + target.browserName + '.jpg', function(err, file) { }); // ブラウザをクローズ browser.close(); // 終了 browser.quit(); }; // 並列で実行するブラウザの設定ファイルをロード browsers.loadConfigFile('config.json'); // テスト実行 browsers.run();
まず、parallel_webdriver.remote()でhubに接続します。
var browsers = parallel_webdriver.remote();
次にconfig.jsonをロードし、browsers.run()で設定数分のbrowsers.testが実行されます。
browsers.loadConfigFile('config.json');
browsers.run();
config.jsonには利用するブラウザが設定されています。
{ "desired" : [ { "name" : "parallel IE", "browserName" : "internet explorer" } , { "name" : "parallel Chrome", "browserName" : "chrome", "chromeOptions" : { "args" : ["--test-type"] } } , { "name" : "parallel FireFox", "browserName" : "firefox" } ] }
IE、Chrome、FireFoxが設定されています。
Chromeのみ--test-typeを追加しています。これは「--ignore-certificate-errors」の警告がでる為の対応です。
テスト内容は単純に
1.googleページを表示
2.「Hello World」を検索
3.検索結果をスクリーンショットで保存
4.ブラウザクローズ
を行うだけです。
実行するとIE、Chrome、FireFoxが次々起動し、上記動作をしてブラウザがクローズされます。
実行後には./resultsにそれぞれのスクリーンショットが保存されているはずです。
chromeとIEの32bitドライバだとスクリーンショットが全画面で撮れませんでした。 IEは64bitドライバだとFireFoxのように全画面のスクリーンショットを撮る事ができました。 Chrome、IEではドライバのVerUpか別途スクリーンショットの撮り方を工夫する必要があるのかも知れません。
※64bitドライバでのresults
所感
今回は検索して画面コピーを残す簡単なものでしたが、実用レベルのテストではDB・WEBサーバの環境をnode毎に用意して同時に実行されても干渉しない様な考慮が必要だったり、アサーションの評価などが必要になると思います。
また、テストデータをnode毎に渡せる方式があれば負荷テストという意味でも使えそうかなという印象を持ちました。
今後、JenkinsやJasmineなども組み合わせたり、モバイル端末を使用したりなど掘り下げたテストの自動化・並列化という検証も面白いのではないかと思いました。