はじめに
Jasmine の RubyGems を使ってコマンドラインから JavaScript のテストを実行できたけど、Ruby からブラウザを自動操縦するのには Selenium WebDriver を使っているみたい。この Selenium WebDriver 、Ruby だけじゃなくて、C# や Java や Python から利用するためのライブラリもあります。ということは、慣れ親しんだ C# で Web アプリの UI のテストが書けますね。
Selenium WebDriver を試してみる
Selenium WebDriver のライブラリは下記のページで入手できます。
C# 用のライブラリを使って、「IE を起動してこのブログを表示し .NET で記事を検索する」テストを書いてみました。
using System; using System.Collections.Generic; using System.Linq; // WebDriver.dll を参照すると下の名前空間が使える。 using OpenQA.Selenium; using OpenQA.Selenium.IE; namespace SeleniumSample { class Program { static void Main(string[] args) { // ブラウザを自動操作するためのドライバを使う。 // IE、Firefox、Chrome、Android、iPhone がそれぞれ用意されている。 using (var driver = new InternetExplorerDriver()) { // ブログを表示 driver.Navigate().GoToUrl("http://d.hatena.ne.jp/griefworker"); // 検索ボックスのエレメント取得 var element = driver.FindElements(By.ClassName("hatena-searchform")) .Select(e => e.FindElement(By.ClassName("searchform-word"))) .First(); // 検索ボックスに入力 element.SendKeys(".NET"); // 検索実行 element.Submit(); // 名前入力 Console.WriteLine("{0} を表示しました。", driver.Title); Console.WriteLine("Enter で終了します。"); Console.ReadLine(); // ブラウザを閉じる driver.Quit(); } } } }
このサンプルを実行すると
Unexpected error launching Internet Explorer. Protected Mode must be set to the same value (enabled or disabled) for all zones. (NoSuchDriver)
っていうエラーが発生するときは、
- インターネットオプションを開く
- セキュリティタブを選択
- インターネット、ローカルイントラネット、信頼済みサイト、制限付きサイトの保護モードを有効にする
- OKをクリック
をやれば解決します。
Selenium IDE も試してみる
C# でブラウザを自動操縦できたことには感動すら覚えたけど、正直、ゴリゴリと Web ブラウザを操縦するコードを書くのは面倒ですよね。大丈夫。Selenium IDE という Firefox アドインを使えば、Firefox 上で行った操作を記録し、テストとして保存できます。
Selenium IDE はこんなやつ。
右上の赤い四角ボタンをクリックすると、次に同じボタンをクリックするまで、ブラウザ上での操作を記録し続けます。記録した操作はテストケースとして保存できます。
また、テストケースのグループを「テストスイート」として保存できます。テストケースやテストスイートは、Selenium IDE で実行するテストとして保存してもいいし、C# や Java などのテストコードの形でエクスポートしてもいいです。
Selenium IDE を使って記録したテストを C# コードとしてエクスポートしたのがこちら。
using System; using System.Text; using System.Text.RegularExpressions; using System.Threading; using NUnit.Framework; using OpenQA.Selenium; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.Support.UI; namespace SeleniumTests { [TestFixture] public class { private IWebDriver driver; private StringBuilder verificationErrors; private string baseURL; [SetUp] public void SetupTest() { driver = new FirefoxDriver(); baseURL = "http://d.hatena.ne.jp/"; verificationErrors = new StringBuilder(); } [TearDown] public void TeardownTest() { try { driver.Quit(); } catch (Exception) { // Ignore errors if unable to close the browser } Assert.AreEqual("", verificationErrors.ToString()); } [Test] public void TheTest() { driver.Navigate().GoToUrl(baseURL + "/griefworker/"); driver.FindElement(By.CssSelector("form.hatena-searchform > input[name=\"word\"]")).Click(); driver.FindElement(By.CssSelector("form.hatena-searchform > input[name=\"word\"]")).Clear(); driver.FindElement(By.CssSelector("form.hatena-searchform > input[name=\"word\"]")).SendKeys(".NET"); driver.FindElement(By.Name(".submit")).Click(); } private bool IsElementPresent(By by) { try { driver.FindElement(by); return true; } catch (NoSuchElementException) { return false; } } } }