Selenium 2 を導入する

複数のブラウザーで Web アプリケーションのエンド・ツー・エンドの機能テストを実行する

Selenium は機能テスト用の Web アプリケーション・テスト・フレームワークとしてよく知られています。Selenium の新しいバージョンである Selenium 2 には、Selenium 1 と WebDriver (Selenium と同様のプロジェクト) の優れた機能が統合されています。この記事を読んで、Selenium 1 から Selenium 2 に簡単に移行する方法を学んでください。サンプル・コードで、Selenium 2 の使用方法、リモートからテストを実行する方法、そして作成済みのテストを Selenium 1 から Selenium 2 に移植する方法を説明します。

Sebastiano Armeli-Battana, Software Engineer, Freelance

Sebastiono Armeli-Battana photoSebastiano Armeli-Battana は、JavaScript および Java 開発を専門とするソフトウェア・エンジニアです。Web 技術に情熱を傾けている彼は、Java 技術を採用している SMS Management & Technology でコンサルタントを務める傍ら、フリーランスの Web エンジニアとしても働いています。彼の著書には、『jQuery plug-in JAIL』があります。彼個人のサイトは http://www.sebastianoarmelibattana.com です。



2012年 4月 05日

はじめに

Selenium は、Web アプリケーションのユーザー・インターフェース (UI) のテストによく使われているフレームワークであり、エンド・ツー・エンドの機能テストを実行するには、極めて強力なツールになります。Selenium では、何種類かのプログラミング言語でテストを作成することができます。作成したテストは、Selenium によって 1 つまたは複数のブラウザーで実行されます。

ブラウザーでの機能テストを自動化できるツールは、Selenium (Selenium 1) だけではありません。同じような目的を持つプロジェクトには、Simon Stewart 氏 (Google) によって作成された WebDriver もあります。ブラウザーを制御するために、WebDriver は独立したクライアントのネイティブ・サポートを利用します。WebDriver が提供するのは Java バインディングのみで、サポートするブラウザーの数は Selenium 1 には及びません。

Selenium 1 + WebDriver = Selenium 2

Selenium 1 と WebDriver が 1 つに統合されて、さらに優れた製品が生まれました。それが、2011年にリリースされた Selenium 2 (Selenium WebDriver) です。Selenium 2 は WebDriver の簡潔なオブジェクト指向の API を継承し、ブラウザーとのやりとりは、そのブラウザーに最善の方法で行います。また、Selenium 2 では JavaScript サンドボックスを使用しませんが、広範なブラウザーと複数の言語バインディングをサポートします。この記事を執筆している時点で、Selenium 2 は以下のブラウザーのドライバーを提供しています。

  • Mozilla Firefox
  • Google Chrome
  • Microsoft Internet Explorer
  • Opera
  • Apple iPhone
  • Android ブラウザー

Selenium 2 では、Java、C#、Ruby、および Python でテストを作成することができます。さらに、Selenium 2 には、Web アプリケーションのテスト用 Java フレームワークである HtmlUnit をベースとしたヘッドレス・ドライバーも用意されています。ただし、HtmlUnit は極めて高速なものの、実際のブラウザーと関連付けるドライバーとしては現実的ではありません。

現在、Selenium 2 はまだ開発中であり、マイナーな問題の解決を行っているところです。現在の最新バージョンは 2.9 です。近い内に Safari と Blackberry のドライバーも統合されることになるはずです。

この記事を読んで、Selenium 2 を使用して Web アプリケーションをテストする方法を学んでください。サンプル・コードに沿って、リモートからテストを実装する方法、そして作成済みのテストを Selenium 1 から Selenium 2 に移植する方法も説明します。

この記事で使用するソース・コードはここからダウンロードしてください。


Selenium 2 の導入

このセクションでは、Web アプリケーションの比較的単純なテストに Selenium 2 フレームワークを使用する方法を説明します。この開発環境で使用する言語は Java です。したがって、Java バインディングが含まれる selenium-java-<バージョン番号>.jar が必要になります (ダウンロードするには、「参考文献」を参照)。Maven プロジェクトの場合には、正しい依存関係を pom.xml に組み込むだけで十分です (リスト 1 を参照)。

リスト 1. Selenium-java 依存関係
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>2.9.0</version>
</dependency>

これで、テストの作成に取り掛かれます。WebDriver API のメイン・コンポーネントは WebDriver インターフェースです。この共通インターフェースの実装は、ブラウザーごとに用意されています。例えば、FirefoxDriver クラスは、Mozilla Firefox の制御に対処します。リスト 2 に、テストの中で特定の実装をインスタンス化する方法を示します。テスト・フレームワークには、各自のニーズに最適なものを使用するので構いません (JUnit または TestNG など)。

リスト 2. FirefoxDriver のインスタンス化
public class Selenium2Example1Test {
    @Test
    public void test() {
        // Instantiate a webDriver implementation
        WebDriver webdriver = new FirefoxDriver();
    }
}

テストするページをロードするには、get() メソッドを使用します。リスト 3 では、上記で作成した Firefox インスタンスに GitHub ホーム・ページ (https://github.com) がロードされます。

リスト 3. テスト対象のページのロード
WebDriver webdriver = new FirefoxDriver();
webdriver.get(https://github.com);

ページをロードした後は、そのページに何らかのアサーションを記述することができます。例えば、リスト 4 に示すように、ページのタイトルが「GitHub - Social Coding」であることをテストするとします。その場合には、WebDriver が提供する getTitle() メソッドを使用して、選択したテスト・フレームワークでアサーションを行うことができます。

リスト 4. ページ・タイトルに関するアサーション
Assert.assertEquals("GitHub - Social Coding", webdriver.getTitle());

テストを完了した後は、quit() メソッドを使って WebDriver インスタンスを終了するのが適切なプラクティスです (リスト 5 を参照)。

リスト 5. WebDriver インスタンスの終了処理
webdriver.quit();

FirefoxDriver は、使用可能な WebDriver 実装の 1 つに過ぎません。同じテストを ChromeDriver を使って実行すれば、テストは Chrome 内で実行されることになります。リスト 6 に、ChromeDriver を使用した場合の完全な例を記載します。

リスト 6. ChromeDriver の例
public class Selenium2Example2Test {
    @Test
    public void test() {
        System.setProperty("webdriver.chrome.driver", 
"src/main/resources/drivers/chrome/chromedriver-mac");

        // Instantiate a webDriver implementation
        WebDriver webdriver = new ChromeDriver();

        webdriver.get(https://github.com);

        Assert.assertEquals("GitHub - Social Coding", webdriver.getTitle());
    }
}

ChromeDriver をインスタンス化する前に、”webdriver.chrome.driver” システム・プロパティーを設定してください。このプロパティーが指すのは、使用している OS での ChromeDriver ファイル (ダウンロードするには、「参考文献」を参照) の場所です。リスト 6 のサンプル・コードでは Mac 用のバージョンを使用していますが、Windows および Linux 用のバージョンも用意されています。

同じテストを Internet Explorer 内で実行する場合は、InterentExplorerDriver クラスのインスタンスを使用します (リスト 7 を参照)。

リスト 7. InternetExplorerDriver のインスタンス化
WebDriver webdriver = new InternetExplorerDriver();

InterenetExplorerDriver を使用する場合、セキュリティー問題が発生して、「保護モードをすべてのゾーンで同じ値 (有効または無効) に設定する必要があります」というメッセージが表示される可能性があります。この問題を解消するには、特定の機能を設定するという方法を使えます (リスト 8 を参照)。

リスト 8. Internet Explorer の場合に設定するセキュリティー機能
DesiredCapabilities capability=DesiredCapabilities.internetExplorer();
capability.setCapability(
              InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_
IGNORING_SECURITY_DOMAINS, true);
WebDriver webdriver = new InternetExplorerDriver(capability);

Opera 内でテストを実行するには、OperaDriver クラスをインスタンス化します。このクラスは、Opera が直接開発したものです。プロジェクトには必ず、該当するドライバーが含まれる JAR を組み込んでください。Maven を使用しているとしたら、リスト 9 に示す依存関係を追加するだけで済みます。

リスト 9. OperaDriver の依存関係
<dependency>
    <groupId>com.opera</groupId>
    <artifactId>operadriver</artifactId>
    <version>0.7.3</version>
</dependency>

iPhone または Android ブラウザー・エミュレーター内でテストを実行するには、さらに構成を追加する必要があります。


Selenium 2 を使用したテスト

Selenium 2 では、前のセクションで説明したテストよりも複雑なテストを作成することができます。このセクションでのテストでは、GitHub のホーム・ページの上部ナビゲーションに 5 つの項目が表示されることを確かめます。具体的には、Signup and Pricing、Explore GitHub、Features、Blog、Login の 5 つの項目です。図 1 に Github のホーム・ページを示します。

図 1. Github のホーム・ページ
Github のホーム・ページ

ここで、上部ナビゲーションの HTML ソース・コードを調べてみましょう (リスト 10 を参照)。

リスト 10. 上部ナビゲーションの HTML ソース・コード
<html>
<head>
    ...
    </head>
    <body class="logged_out env-production">
        <div id="main">
            <div id="header" class="true">
...
                <div class="topsearch">
                        <ul class="nav logged_out">
                            <li class="pricing">
<a href="https://github.com/plans">Signup and Pricing</a>
</li>
                            <li class="explore">
<a href="https://github.com/explore">Explore GitHub</a>
</li>
                          <li class="features">
<a href="https://github.com/features">Features</a>
</li>
                            <li class="blog">
<a href="https://github.com/blog">Blog</a>
</li>
                          <li class="login">
<a href="https://github.com/login">Login</a>
</li>
                        </ul>
</div>
...
            </div>
            ...
        </div>
       ...
    </body>
</html>

WebDriver API を使用すれば、HTML コードから、テストする必要のある要素を取得することができます。findElement() メソッドと findElements() メソッドは、共通インターフェース WebElement のインスタンス、またはインスタンスのリストを返します。簡潔なオブジェクト指向の形を取った WebElement インターフェースは、ページ内のすべての要素に使用されます。この API には、UI 要素を見つけるためのストラテジーがいくつかあります。これらのストラテジーは、findElement() および findElements() メソッドに渡されるパラメーターのタイプによって表されます。リスト 11 に、抽象クラス By に適用される異なる種類のメソッドごとに、どのストラテジーが採用されるかを示します。

リスト 11. findElement() メソッドを使用する例
WebElement element1 = webdriver.findElement(By.id("header"));
WebElement element2 = webdriver.findElement(By.name("name"));
WebElement element3 = webdriver.findElement(By.tagName("a"));
WebElement element4 = webdriver.findElement(By.xpath("//a[@title='logo']")); 
WebElement element5 = webdriver.findElement(By.cssSelector(".feautures"));
WebElement element6 = webdriver.findElement(By.linkText("Blog"));
WebElement element7 = webdriver.findElement(By.partialLinkText("Ruby"));
WebElement element8 = webdriver.findElement(By.className("login"));

リスト 11 に示されたストラテジーのうちの 1 つを使用して、最初の要素を取得するテストの作成に取り掛かります。つまり、クラスが nav に設定された ul タグの中に含まれる最初の li タグを取得します。リスト 12 では (By.xpath()) という XPath を使用します。

リスト 12. XPath
List<WebElement> webElements = webdriver.findElements(By
            .xpath("//ul[@class='nav logged_out']/li"));

リスト 13 では、CSS セレクター (By.cssSelector()) を使用して li タグを取得します。

リスト 13. CSS セレクター
List<WebElement> webElements = webdriver.findElements(By
            .cssSelector("ul.nav li"));

この時点で、取得する項目の数に関する最初のアサーションを行うことができます (リスト 14 を参照)。

リスト 14. 項目数に関するアサーション
Assert.assertEquals(5, webElements.size());

上記のステップで、li タグの数が 5 であることを検証しました。

次のステップでは、各 li タグに含まれる個々のアンカー (a タグ) を取得します。リスト 15 に示すのは、最初の li タグに含まれるアンカーを取得する方法です。この例では、tagName ストラテジー (By.tagName()) を使用します。

リスト 15. 最初の li タグに含まれるアンカーの取得
WebElement anchor1 = webElements.get(0).findElement(By.tagName("a"));

同じような方法で、5 つのアンカーのすべてを収集することができます (リスト 16 を参照)。

リスト 16. li タグに含まれるすべてのアンカーの取得LI tag
WebElement anchor1 = webElements.get(0).findElement(By.tagName("a"));
WebElement anchor2 = webElements.get(1).findElement(By.tagName("a"));
WebElement anchor3 = webElements.get(2).findElement(By.tagName("a"));
WebElement anchor4 = webElements.get(3).findElement(By.tagName("a"));
WebElement anchor5 = webElements.get(4).findElement(By.tagName("a"));

この段階で、アンカーに含まれるテキストが、期待される文字列と一致するかどうかを検証することができます。タグ内のテキストを取得するために、WebDriver では getText() メソッドを用意しています。リスト 17 に、完全なテスト方法を記載します。アサーションは、テストの一番下にあります。

リスト 17. 完全なテスト
@Test
public void test() {
WebDriver webdriver = new FirefoxDriver();    
webdriver.get("https://github.com");
List<WebElement> webElements = webdriver.findElements(By
                .xpath("//ul[@class='nav logged_out']/li"));
Assert.assertEquals(5, webElements.size());

    // Retrieve the anchors
    WebElement anchor1 = webElements.get(0).findElement(By.tagName("a"));
    WebElement anchor2 = webElements.get(1).findElement(By.tagName("a"));
    WebElement anchor3 = webElements.get(2).findElement(By.tagName("a"));
    WebElement anchor4 = webElements.get(3).findElement(By.tagName("a"));
    WebElement anchor5 = webElements.get(4).findElement(By.tagName("a"));
    
// Assertions    
    Assert.assertEquals("Signup and Pricing", anchor1.getText());
    Assert.assertEquals("Explore GitHub", anchor2.getText());
    Assert.assertEquals("Features", anchor3.getText());
    Assert.assertEquals("Blog", anchor4.getText());
    Assert.assertEquals("Login", anchor5.getText());
        
    webdriver.quit();

}

このテストを開始すると、新しい Firefox ウィンドウが開きます。このウィンドウは、すべてのアサーションが実行されるまで開いたままになります。


Selenium Grid 2 を使用したリモートからのテスト

Selenium 2 では、テストをローカルで実行することも、リモートから実行することもできます。リモートから実行する場合、テストには RemoteWebDriver という WebDriver インターフェースの実装を使用しなければなりません。実行するブラウザーを指定するには、DesiredCapabilities クラスを使用します。リスト 18 に一例を記載します。

リスト 18. RemoteWebDriver クラスと DesiredCapabilities クラス
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setBrowserName("firefox");
capabilities.setVersion("7");
capabilities.setPlatform("MAC");
WebDriver webdriver = new RemoteWebDriver(capabilities);

DesiredCapabilities クラスを使用して、ブラウザー名、プラットフォーム、およびブラウザーのバージョンを指定することができます。また、ブラウザーがサポートできるその他多くの機能を指定することもできます。

リモートから構造化されたテストを実行して、複数のブラウザー (そして、おそらくは各種の仮想マシン) を実行しなければならない場合には、Selenium Grid が優れたソリューションを提供します。

Selenium Grid 2 は、それぞれに異なるブラウザーを表すノードが、ハブに対して自身を登録するためのインフラストラクチャーとなります。個々のテストは、それぞれの要求を適切なブラウザーにディスパッチする役目を担うハブを呼び出します。ハブとノードが実行される仮想マシンは、同じである必要はありません。

リモートからテストする場合は、使用するマシンのそれぞれに selenium-server-standalone-<バージョン番号>.jar をダウンロードする必要があります。マシンにハブをインストールするには、必要な JAR をダウンロードしたフォルダーにカレント・ディレクトリーを変更し、リスト 19 に記載するコマンドを呼び出します。

リスト 19. ハブの起動
java -jar selenium-server-standalone-2.9.0.jar ?role hub

Selenium Grid 2 コンソールには、http://localhost:4444/grid/console でアクセスすることができます。このコンソールには、使用可能なノードがすべて表示されます。ノードを登録するには、リスト 20 に記載するコマンドを実行します。

リスト 20 ハブへのノードの登録
java -jar selenium-server-standalone-2.9.0.jar 
-role webdriver ?hub http://localhost:4444/grid/register -port 5556

リスト 20 のコマンドは、デフォルトで 7 つのブラウザーを登録します。そのうちの 5 つは Firefox インスタンス、後は Chrome インスタンスと Internet Explorer インスタンスがそれぞれ 1 つずつです。リスト 21 に、特定のポートで特定のブラウザーをターゲットにする方法を示します。

リスト 21. ハブに登録された Chrome インスタンス
java -jar selenium-server-standalone-2.9.0.jar -role webdriver 
-hub http://localhost:4444/grid/register -port 5556 -browser 
browserName=chrome,version=14,platform=MAC

いくつかのブラウザーを登録すると Selenium Grid 2 コンソールは図 2 のような表示内容になっているはずです。

図 2. Selenium Grid 2 コンソールのビュー
Grid 2 コンソールのビュー

グリッドを使用するためには、テスト・ケース内に、ハブの URL と制御対象のブラウザーを指定する必要があります。リスト 22 に、RemoteWebDriver クラスのコンストラクターがハブの URL と、特定のブラウザーを定義する DesiredCapabilities のインスタンスを引数として取るコード・ブロックを示します。

リスト 22. RemoteWebDriver のインスタンス化
DesiredCapabilities capability = new DesiredCapabilities();
capability.setBrowserName("chrome");
capability.setVersion("14");
capability.setPlatform(Platform.MAC);
WebDriver webdriver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),
 capability);

上記の例でハブが起動するのは、Chrome バージョン 14 (リスト 21 で登録したもの) に関連付けられたノードです。

Selenium Grid 2 には Selenium 1 との後方互換性もあります。したがって、ハブには Selenium 1 RC ノード (Selenium 1 インフラストラクチャーの一部) も登録することができます (リスト 23 を参照)。

リスト 23. Selenium 1 RC ノードの登録
java ?jar selenium-server-standalone-2.9.0.jar 
-role rc ?hub http://localhost:4444/grid/register -port 5557

Selenium 1 から Selenium 2 へのテストの移植

作成済みのテストを Selenium 1 から Selenium 2 に移植する必要がある場合、その作業は極めてスムーズに行われます。Selenium 1 API は新しい API の下に保持されているため、Selenium 2 には完全な後方互換性があります。

テストを Selenium 1 から Selenium 2 に変換するのは、WebDriverBackedSelenium クラスのおかげで簡単な作業になっています。このクラスは、WebDriver のインスタンスとテスト対象の URL を引数として取り、Selenium インスタンスを返します。リスト 24 に記載するサンプル・コードはリスト 16 と同じものですが、今回は Selenium 2 に統合された Selenium 1 API を使用しています。

リスト 24. Selenium 2 に統合された Selenium 1
@Test
public void test() {
    String url = "https://github.com";
WebDriver webdriver = new FirefoxDriver();
webdriver.get(url);
Selenium selenium = new WebDriverBackedSelenium(webdriver, url);
    selenium.open(url);
        
// Get the number of LIs
    Number lis = selenium.getXpathCount("//ul[@class='nav logged_out']/li");

    Assert.assertEquals(5, lis.intValue());

    // Retrieve the text inside the anchors
    String anchor1Text = selenium.getText("//ul[@class='nav logged_out']/li[1]/a");
    String anchor2Text = selenium.getText("//ul[@class='nav logged_out']/li[2]/a");
    String anchor3Text = selenium.getText("//ul[@class='nav logged_out']/li[3]/a");
    String anchor4Text = selenium.getText("//ul[@class='nav logged_out']/li[4]/a");
    String anchor5Text = selenium.getText("//ul[@class='nav logged_out']/li[5]/a");
        
    Assert.assertEquals("Signup and Pricing", anchor1Text);
    Assert.assertEquals("Explore GitHub", anchor2Text);
    Assert.assertEquals("Features", anchor3Text);
    Assert.assertEquals("Blog", anchor4Text);
    Assert.assertEquals("Login", anchor5Text);
        
    webdriver.quit();
}

Selenium 2 では開発者をより重視し、Selenium 1 よりも簡潔な API を提供しています。それは、getText() メソッドおよび getXpathCount() メソッドのシグニチャーを見れば明らかです。また、Selenium 2 API はよりオブジェクト指向となっており、例えば UI 要素のオブジェクトを文字列のみとして扱うことはできません。


まとめ

Selenium 2 は、ブラウザー内でのテスト自動化における進化を示しています。Selenium 2 は Selenium 1 と WebDriver の優れた点を取り入れ、複数のブラウザーと緊密に統合します。また、開発者のニーズを見事に満たす新しい API は、オブジェクト指向の手法を提供し、テスト内でさまざまなパターンを使用できるようにしています。さらに、Selenium 2 には以下の利点もあります。

  • 同一生成元ポリシーに関連する制約を克服しています。
  • ポップアップのサポートを改善しています。
  • キーボードとマウスのネイティブな相互作用を効率的に制御します。

Selenium 2 に組み込まれている Selenium Grid の新しいバージョンによって、Selenium 2 ではリモートから簡単にテストを起動できるようになっています。Selenium 2 には Selenium 1 との後方互換性があるため、新しいバージョンにアップグレードするのは簡単この上ありません。Selenium 2 を利用して、アプリケーションが要件どおりに機能することを確実にしてください。


ダウンロード

内容ファイル名サイズ
Article source codeselenium2-gettingStarted5,243KB

参考文献

学ぶために

  • Selenium: Selenium ブラウザー自動化フレームワークの開発者向けの詳細を学んでください。
  • Selenium HQ:Selenium フレームワークを使用して開発している場合には、Selenium がブラウザーを自動化する方法の詳細を読んでください。
  • Selenium 2 ドキュメント: Selenium 2.0 および WebDriver に関する詳細な情報を入手してください。
  • Selenium プロジェクトの歴史: テストを自動化するための Selenium プロジェクトが歩んできた歴史について学んでください。
  • Selenium Wiki: さまざまなトピックで Selenium に関する情報を探ってください。
  • Getting started with Selenium 2 and WebDriver」(QA Automation、2011年8月): サーバーの起動方法と停止方法、および WebDriver をインスタンス化する方法を実践的な手順で説明しています。
  • eveloperWorks Web development ゾーンでは、多種多様な Web ベースのソリューションを取り上げた記事を揃えています。
  • developerWorks の Technical events and webcasts: これらのセッションで最新情報を入手してください。
  • Twitter での developerWorks: 今すぐ登録して developerWorks のツイートをフォローしてください。

製品や技術を入手するために

  • Selenium 2: 最新バージョンをダウンロードしてください。
  • ChromeDriver ファイル: ご使用の OS に対応した ChromeDriver を入手してください。
  • IBM 製品の評価版のダウンロード:DB2、Lotus、Rational、Tivoli、および WebSphere のアプリケーション開発ツールとミドルウェア製品を体験するには、評価版をダウンロードするか、IBM SOA Sandbox のオンライン試用版を試してみてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。プロフィールで選択した情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=807607
ArticleTitle=Selenium 2 を導入する
publish-date=04052012