ユーザー拡張スクリプト

注意: この章はほぼ完成していますが、レビューと編集はまだ行われていません。

はじめに

Selenium は、独自のアクション、アサーション、ロケータストラテジーを追加することで簡単に拡張できます。具体的な手順としては、JavaScript を使って、Selenium オブジェクトプロトタイプと PageBot オブジェクトプロトタイプにメソッドを追加します。Selenium は起動時にこれらのプロトタイプのメソッドを自動的に走査し、名前のパターンを使って、どれがアクション、アサーション、およびロケータであるかを認識します。以下に示す例では、JavaScript を使って Selenium を拡張する方法を示します。

アクション

“do” で始まる Selenium プロトタイプのすべてのメソッドは、アクションとして追加されます。各アクション foo に対しては、アクション fooAndWait も登録されます。アクションメソッドはパラメータを 2 つまで取ることができ、これらのパラメータはテストの中で 2 列目と 3 列目の値として渡されます。次に示すのは、テキストボックスにテキストを 2 回入力する “typeRepeated” アクションを Selenium に追加する例です。

Selenium.prototype.doTypeRepeated = function(locator, text) {
    // All locator-strategies are automatically handled by "findElement"
    var element = this.page().findElement(locator);

    // Create the text to type
    var valueToType = text + text;

    // Replace the element text with the new text
    this.page().replaceText(element, valueToType);
};

アクセサ/アサーション

Selenium プロトタイプのすべての getFoo メソッドおよび isFoo メソッドは、アクセサ (storeFoo) として追加されます。各アクセサに対しては、assertFoo、verifyFoo、および waitForFoo が登録されます。assert メソッドはパラメータを 2 つまで取ることができ、これらのパラメータはテストの中で 2 列目と 3 列目の値として渡されます。独自のアサーションをシンプルな “assert” メソッドとして文字通り定義することもでき、この場合は “verify” コマンドと “waitFor” コマンドが自動的に生成されます。次に示すのは、要素の値が、指定したテキストを反復したものかどうかを調べる valueRepeated アサーションを追加する例です。この場合に、テストで利用可能になる 2 つのコマンドは、assertValueRepeated と verifyValueRepeated です。

Selenium.prototype.assertValueRepeated = function(locator, text) {
    // All locator-strategies are automatically handled by "findElement"
    var element = this.page().findElement(locator);

    // Create the text to verify
    var expectedValue = text + text;

    // Get the actual element value
    var actualValue = element.value;

    // Make sure the actual value matches the expected
    Assert.matches(expectedValue, actualValue);
};

すべての getFoo に対して自動的に利用可能になる storeFoo、assertFoo、assertNotFoo、waitForFoo、waitForNotFoo

Selenium プロトタイプのすべての getFoo メソッドおよび isFoo メソッドに対しては、storeFoo、assertFoo、assertNotFoo、verifyFoo、verifyNotFoo、waitForFoo、および waitForNotFoo コマンドが自動的に利用可能になります。次に示す getTextLength() メソッドを追加すると、 storeTextLengthassertTextLengthassertNotTextLengthverifyTextLengthverifyNotTextLengthwaitForTextLength 、および waitForNotTextLength コマンドが自動的に利用可能になります。

Selenium.prototype.getTextLength = function(locator, text) {
    return this.getText(locator).length;
};

なお、上の assertValueRepeated メソッドは、 isValueRepeated を使って実装することもできる点に注意してください。この場合には、assertNotValueRepeated、storeValueRepeated、waitForValueRepeated、および waitForNotValueRepeated が自動的に利用可能になるという付加的メリットがあります。

ロケータストラテジー

PageBot プロトタイプのすべての locateElementByFoo メソッドは、ロケータストラテジーとして追加されます。ロケータストラテジーは引数を 2 つ取ります。最初の引数はロケータ文字列 (プリフィックスを除いたもの) で、2 番目の引数は検索対象のドキュメントです。次に示すのは、value 属性が、指定された値の反復に等しい最初の要素を見つける “valuerepeated=” ロケータを追加する例です。

// The "inDocument" is a the document you are searching.
PageBot.prototype.locateElementByValueRepeated = function(text, inDocument) {
    // Create the text to search for
    var expectedValue = text + text;

    // Loop through all elements, looking for ones that have
    // a value === our expected value
    var allElements = inDocument.getElementsByTagName("*");
    for (var i = 0; i < allElements.length; i++) {
        var testElement = allElements[i];
        if (testElement.value && testElement.value === expectedValue) {
            return testElement;
        }
    }
    return null;
};

Selenium-IDE でのユーザー拡張スクリプトの使用

Selenium IDE でユーザー拡張スクリプトを使うのは非常に簡単です。

  1. ユーザー拡張スクリプトを作成し、user-extensions.js として保存します。技術的にはファイル名をこのようにする必要はありませんが、慣習に従ってこのように名前を付けておきます。
  2. Firefox を起動し、Selenium-IDE を開きます。
  3. [オプション] メニューの [設定] をクリックします。
  4. [Selenium Core 拡張スクリプト (user-extensions.js) のパス] で [参照] をクリックし、保存した user-extensions.js ファイルを指定します。[OK] をクリックします。
  5. ユーザー拡張スクリプトを読み込ませるには、Selenium-IDE をいったん閉じて、再起動する必要があります。
  6. 空のテストで新しいコマンドを作成すると、ユーザー拡張スクリプトで作成したコマンドが [コマンド] ボックスのドロップダウンリストに表示されるようになります。

Selenium RC でのユーザー拡張スクリプトの使用

Google で “Selenium RC user-extension” を検索すると、この機能を使うためのさまざまなアプローチが見つかります。以下に示すのは、Selenium 開発チームが公式に推奨するアプローチです。

C#

  1. ユーザー拡張スクリプトを Selenium サーバーと同じディレクトリに置きます。
  2. Selenium-IDE によって生成されたクライアントコードを使う場合は、いくらか編集作業が必要になります。まず、クラススコープを持つ HttpCommandProcessor オブジェクトを作成する必要があります (あとに示すコードの中では、SetupTest メソッドの外側で、 private StringBuilder verificationErrors; のすぐ下)。
HttpCommandProcessor proc;
  1. 次に、 DefaultSelenium オブジェクトのインスタンス化で必要になる HttpCommandProcessor オブジェクトをインスタンス化します。これは、テストのセットアップの中で行うことができます。
proc = new HttpCommandProcessor("localhost", 4444, "*iexplore", "http://google.ca/");
  1. 作成した HttpCommandProcessor オブジェクトを使って、 DefaultSelenium オブジェクトをインスタンス化します。
selenium = new DefaultSelenium(proc);
  1. テストコードの中では、 HttpCommandProcessorDoCommand() メソッドで拡張スクリプトのコマンドを呼び出すことで、コマンドを実行します。 DoCommand() メソッドは引数を 2 つ取ります。最初の引数は、使用するユーザー拡張メソッドを特定する文字列です。2 番目の引数は、引数を渡すための文字列配列です。ユーザー拡張スクリプトで大文字小文字をどのように指定しているかにかかわらず、関数の最初の文字が小文字になっている点に注意してください。Selenium は、JavaScript の名前付け規則を守るために、関数の先頭の文字を自動的に小文字に変換します。JavaScript は大文字小文字を区別するので、コマンドを大文字で始めるとテストは失敗します。inputParams は、JavaScript ユーザー拡張コマンドに渡す引数の配列です。例では、ユーザー拡張コマンドが取る引数は 1 つだけなので、配列に含まれる文字列は 1 つだけですが、もっと長い配列の場合は、各添字がユーザー拡張コマンドのパラメータに対応することになります。なお、Selenium-IDE 用に設計されたユーザー拡張スクリプトでは、2 つまでしか引数を取らないことに注意してください。
string[] inputParams = {"Hello World"};
proc.DoCommand("alertWrapper", inputParams);
  1. -userExtensions 引数に user-extensinos.js ファイルを指定してテストサーバーを起動します。
java -jar selenium-server.jar -userExtensions user-extensions.js
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using NUnit.Framework;
using Selenium;

namespace SeleniumTests
{
        [TestFixture]
        public class NewTest
        {

                private ISelenium selenium;
                private StringBuilder verificationErrors;
                private HttpCommandProcessor proc;

                [SetUp]
                public void SetupTest()
                {
                        proc = new HttpCommandProcessor("localhost", 4444, "*iexplore", "http://google.ca/");
                        selenium = new DefaultSelenium(proc);
                        //selenium = new DefaultSelenium("localhost", 4444, "*iexplore", "http://google.ca/");
                        selenium.Start();
                        verificationErrors = new StringBuilder();

                }

                [TearDown]
                public void TeardownTest()
                {
                        try
                        {
                                selenium.Stop();
                        }
                        catch (Exception)
                        {
                                // Ignore errors if unable to close the browser
                        }
                        Assert.AreEqual("", verificationErrors.ToString());
                }

                [Test]
                public void TheNewTest()
                {
                        selenium.Open("/");
                        string[] inputParams = {"Hello World",};
                        proc.DoCommand("alertWrapper", inputParams);
                }
        }
}

End