8

複数のブラウザーでSeleniumGrid/WebDriverを介してテストを実行する最初のデータ駆動型テストフレームワークをまとめようとしています。現在、私は独自のクラスに各テストケースを持っており、ブラウザーをパラメーター化するため、各ブラウザーで各テストケースを1回実行します。

これは大きなテストフレームワークでは一般的ですか?または、各テストケースをコピーして、独自のクラスの各ブラウザに微調整する必要がありますか?したがって、chrome、firefox、IEをテストしている場合、それぞれに「TestCase1Chrome」、「TestCase1FireFox」、「TestCase1IE」のようなクラスが必要ですか?または、「TestCase1」だけで、各ブラウザで3回実行するようにテストをパラメータ化しますか?他の人がそれをどのように行うのか疑問に思っています。

テストをテストケースごとに1つのクラスにパラメーター化すると、ブラウザー固有ではないコードの保守が容易になり、ブラウザーケースごとに1つずつクラスを複製すると、ブラウザー固有のコードの保守が容易になります。たとえば、ブラウザ固有のコードを言うとき、アイテムをクリックします。ChromeDriverでは、一部の要素の中央をクリックできませんが、FirefoxDriverではクリックできます。したがって、要素をクリックするためだけに2つの異なるコードブロックが必要になる可能性があります(中央でクリックできない場合)。

Seleniumを使用するQAエンジニアを採用している方にとって、ここでのベストプラクティスは何でしょうか。

4

4 に答える 4

4

私は現在、毎日約75k〜90kのテストを実行するプロジェクトに取り組んでいます。ブラウザをパラメータとしてテストに渡します。理由:

  1. あなたがあなたの質問で述べたように、これはメンテナンスに役立ちます。
  2. ブラウザ固有のコードはあまり多くありません。ブラウザ固有のコードが多すぎる場合は、Webドライバ自体に問題があると思います。なぜなら、selenium / webdriverの利点の1つは、コードを1回記述して、サポートされている任意のブラウザーに対して実行できることです。

私のコード構造とあなたが問題に言及したものとの違いは、各テストケースのテストクラスがないということです。テストは、私がテストする機能に基づいて分割され、各機能にはクラスがあります。そして、そのクラスはすべてのテストをメソッドとして保持します。これらのメソッドを並行して呼び出すことができるように、testNGを使用しています。これはあなたのAUTに合わないかもしれません。

于 2013-01-24T23:16:22.597 に答える
3

質問で言及したコード構造を維持すると、遅かれ早かれそれを維持することは悪夢になります。ルールに固執するようにしてください:すべてのブラウザ(環境)に対して同じテストコード(1回記述)。

この状態では、2つの問題を解決する必要があります。

1)選択したすべてのブラウザでテストを実行する方法

2)テストコードを汚染せずに特定のブラウザの回避策を適用する方法

実際、これはあなたの質問のようです。

これが私が最初の問題を解決した方法です。まず、テストするすべての環境を定義しました。テストを実行するすべての条件(ブラウザー名、バージョン番号、OSなど)を「環境」と呼びます。したがって、テストコードとは別に、次のような列挙型を作成しました。

public enum Environments {

    FF_18_WIN7("firefox", "18", Platform.WINDOWS),
    CHR_24_WIN7("chrome", "24", Platform.WINDOWS),
    IE_9_WIN7("internet explorer", "9", Platform.WINDOWS)
    ;

    private final DesiredCapabilities capabilities;
    private final String browserName;
    private final String version;
    private final Platform platform;

    Environments(final String browserName, final String version, final Platform platform) {
        this.browserName = browserName;
        this.version = version;
        this.platform = platform;
        capabilities = new DesiredCapabilities();
    }

    public DesiredCapabilities capabilities() {
        capabilities.setBrowserName(browserName);
        capabilities.setVersion(version);
        capabilities.setPlatform(platform);
        return this.capabilities;
    }

    public String browserName() {
        return browserName;
    }
}

必要なときにいつでも環境を簡単に変更および追加できます。お気づきのとおり、私はこれを使用して、後で特定のWebDriverを作成するために使用されるDesiredCapabilitiesを作成および取得しています。

定義されたすべての環境でテストを実行するために、JUnit(私の場合は4.10)のorg.junit.experimental.theoriesを使用しました。

@RunWith(MyRunnerForSeleniumTests.class)
public class MyWebComponentTestClassIT {

    @Rule 
    public MySeleniumRule selenium = new MySeleniumRule();

    @DataPoints 
    public static Environments[] enviroments = Environments.values();

    @Theory
    public void sample_test(final Environments environment) {

        Page initialPage = LoginPage.login(selenium.driverFor(environment), selenium.getUserName(), selenium.getUserPassword());

        // your test code here

    }   
}

テストには(通常のJUnitテストのようにでは@Theoryなく)という注釈が付けられ、パラメーターが渡されます。@Test次に、このパラメーターの定義されたすべての値に対して各テストが実行されます。これは、。として注釈が付けられた値の配列である必要があります@DataPoints。また、から伸びるランナーを使用する必要がありますorg.junit.experimental.theories.Theories。私はテストの準備に使用org.junit.rulesし、必要なすべての配管をそこに置きます。ご覧のとおり、私もルールを通じて特定の機能ドライバーを取得しています。ただし、テストでは次のコードを使用できます。

RemoteWebDriver driver = new RemoteWebDriver(new URL(some_url_string), environment.capabilities());

重要なのは、ルールにそれを含めると、コードを1回記述して、すべてのテストに使用するということです。Pageクラスは、ドライバーの機能(要素の検索、ナビゲートなど)を使用するすべてのコードを配置するクラスです。このようにして、テストコードはきちんと明確に保たれ、もう一度、一度記述してすべてのテストで使用します。だから、これは最初の問題の解決策です。(TestNGでも同様のことができることは知っていますが、試していません。)

2番目の問題を解決するために、ブラウザー固有の回避策のすべてのコードを保持する特別なパッケージを作成しました。これは、一部のブラウザでたまたま異なる(またはバグがある)共通コードを含む抽象クラス(例:BrowserSpecific)で構成されています。同じパッケージに、テストで使用されるすべてのブラウザーに固有のクラスがあり、それぞれがBrowserSpecificを拡張します。

あなたが言及したChromeドライバーのバグに対してどのように機能するかを次に示します。clickOnButton影響を受ける動作の共通コードを使用して、BrowserSpecificでメソッドを作成します。

public abstract class BrowserSpecific {

    protected final RemoteWebDriver driver;

    protected BrowserSpecific(final RemoteWebDriver driver) {
        this.driver = driver;
    }

    public static BrowserSpecific aBrowserSpecificFor(final RemoteWebDriver driver) {
        BrowserSpecific browserSpecific = null;

        if (Environments.FF_18_WIN7.browserName().contains(driver.getCapabilities().getBrowserName())) {
            browserSpecific = new FireFoxSpecific(driver);
        }

        if (Environments.CHR_24_WIN7.browserName().contains(driver.getCapabilities().getBrowserName())) {
            browserSpecific = new ChromeSpecific(driver);
        }

        if (Environments.IE_9_WIN7.browserName().contains(driver.getCapabilities().getBrowserName())) {
            browserSpecific = new InternetExplorerSpecific(driver);
        }

        return browserSpecific;
    }

    public void clickOnButton(final WebElement button) {
            button.click();
    }
}

次に、回避策コードを配置する特定のクラス、たとえばChromeSpecificでこのメソッドをオーバーライドします。

public class ChromeSpecific extends BrowserSpecific {

        ChromeSpecific(final RemoteWebDriver driver) {
            super(driver);
        }

        @Override
        public void clickOnButton(final WebElement button) {

        // This is the Chrome workaround

            String script = MessageFormat.format("window.scrollTo(0, {0});", button.getLocation().y);
            driver.executeScript(script);

        // Followed by common behaviour of all the browsers
            super.clickOnButton(button);
        }
}

一部のブラウザの特定の動作を考慮に入れる必要がある場合は、次のことを行います。

 aBrowserSpecificFor(driver).clickOnButton(logoutButton);

それ以外の:

 button.click();

このようにして、私の共通コードでは、回避策が適用された場所を簡単に識別でき、回避策を共通コードから分離したままにします。バグは通常解決されており、回避策は変更または削除される可能性があるため、保守が容易だと思います。

テストの実行について最後に一言。Selenium Gridを使用する場合は、テストを並行して実行する可能性を使用する必要があるため、JUnitテスト(v。4.7以降で使用可能)用にこの機能を構成することを忘れないでください。

于 2013-02-01T14:33:53.650 に答える
1

組織ではtestngを使用し、testngが提供するパラメーターオプションを使用して、環境、つまり使用するブラウザー、実行するマシン、およびenvconfigに必要なその他の構成を指定します。ブラウザ名は、何をどこで実行する必要があるかを制御するxmlファイルを介して送信されます。グローバル変数として設定されます。追加で行ったことは、これらのグローバル変数をオーバーライドできるカスタムアノテーションがあります。つまり、テストがChromeでのみ実行され、他のブラウザーでは実行されない場合は、カスタムアノテーションで同じものを指定します。したがって、パラメーターがFFで実行されていると言っても、chromeで注釈が付けられている場合は、常にchromeで実行されます。

どういうわけか、ブラウザごとに1つのクラスを作成するのは良い考えではないと思います。フローが変化するか、あちこちに少しあり、1つではなく3つのクラスを変更することを想像してみてください。そして、ブラウザの数が増えると、もう1つのクラスになります。

私が提案するのは、抽出するブラウザ固有のコードを用意することです。したがって、クリック動作がブラウザ固有である場合は、それをオーバーライドして、ブラウザに基づいて適切なチェックまたは失敗処理を実行します。

于 2013-01-25T10:41:28.310 に答える
0

私はこのようにしていますが、これはグリッドやRCを念頭に置いていない純粋なWebDriverであることに注意してください。

// Utility class snippet
// Test classes import this with:  import static utility.*;
public static WebDriver driver;
public static void initializeBrowser( String type ) {
  if ( type.equalsIgnoreCase( "firefox" ) ) {
    driver = new FirefoxDriver();
  } else if ( type.equalsIgnoreCase( "ie" ) ) {
    driver = new InternetExplorerDriver();
  }
  driver.manage().timeouts().implicitlyWait( 10000, TimeUnit.MILLISECONDS );
  driver.manage().window().setPosition(new Point(200, 10));
  driver.manage().window().setSize(new Dimension(1200, 800));
}

ここで、JUnit 4.11 +を使用すると、パラメータファイルは次のようになる必要があります。

firefox, test1, param1, param2
firefox, test2, param1, param2
firefox, test3, param1, param2
ie, test1, param1, param2
ie, test2, param1, param2
ie, test3, param1, param2

次に、単一の.CSVパラメーター化テストクラス(複数のブラウザータイプを開始する予定)を使用して、@Before注釈付きメソッドで次のようにします。

  1. 現在のパラメータテストがこのブラウザタイプの最初のテストであり、まだ開いているウィンドウが存在しない場合は、現在のタイプの新しいブラウザウィンドウを開きます。
  2. ブラウザがすでに開いていて、ブラウザの種類が同じである場合は、同じドライバオブジェクトを再利用してください。
  3. ブラウザが現在のテストとは異なるタイプで開いている場合は、ブラウザを閉じて、正しいタイプのブラウザを再度開きます。

もちろん、私の答えはパラメータの処理方法を教えてくれません。それはあなたが理解できるように残しておきます。

于 2013-01-17T21:20:26.943 に答える