Selenium でブラウザを自動操縦して Web アプリをテストする

はじめに

Jasmine の RubyGems を使ってコマンドラインから JavaScript のテストを実行できたけど、Ruby からブラウザを自動操縦するのには Selenium WebDriver を使っているみたい。この Selenium WebDriver 、Ruby だけじゃなくて、C#JavaPython から利用するためのライブラリもあります。ということは、慣れ親しんだ 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、FirefoxChromeAndroidiPhone がそれぞれ用意されている。
            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)

っていうエラーが発生するときは、

  1. インターネットオプションを開く
  2. セキュリティタブを選択
  3. インターネット、ローカルイントラネット、信頼済みサイト、制限付きサイトの保護モードを有効にする
  4. OKをクリック

をやれば解決します。

Selenium IDE も試してみる

C# でブラウザを自動操縦できたことには感動すら覚えたけど、正直、ゴリゴリと Web ブラウザを操縦するコードを書くのは面倒ですよね。大丈夫。Selenium IDE という Firefox アドインを使えば、Firefox 上で行った操作を記録し、テストとして保存できます。

Selenium IDE はこんなやつ。

f:id:griefworker:20120320122427p:image

右上の赤い四角ボタンをクリックすると、次に同じボタンをクリックするまで、ブラウザ上での操作を記録し続けます。記録した操作はテストケースとして保存できます。

また、テストケースのグループを「テストスイート」として保存できます。テストケースやテストスイートは、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;
            }
        }
    }
}

NUnit のテストなのが残念。まぁ、名前空間や属性名を置換すれば MSTest のテストとして使えるかな。

まとめ

Jasmine と Selenium を使えば、Web アプリの UI の大部分がテストできそうです。しかも、Selenium IDE を使えばテストコードの生成までできてしまうときた。Selenium こんなに便利だったのか。なんで今まで試そうともしなかったんだろう。

人手でやっていたテストの多くは、今思うと Selenium で置き変え可能なものが多かった気がします。時間がもったいなかったな。試そうとすらしなかったのはもはや罪ですね。