0

私は 2.31 バージョン、testng 6.8 を使用しており、IE 8 でテストを実行しています。このスキームでテストを書いています。次のようになります。

@Test(description="click Save Button ", dependsOnMethods = { "edit form" })
public void clickSaveButton(ITestContext context) {
    page.clickSaveButton(driver);

}

次に、ご覧のとおり、要素 ID、xpath などを格納するページ クラスがあります。次のように表示されます。

public void clickSaveButton(WebDriver driver){
    Configuration.clickfoundElement(By.id(conf.get("saveButton")), driver);
}

conf は、プロパティ ファイルを表すオブジェクトです。最後に、次のようなことを行う Configuration クラスがあります。

public static void clickfoundElement(By by, WebDriver driver){
    int attempts = 0;

    while(attempts < 10) {
        try {

            driver.findElement(by).click();
            break;
        } catch(NoSuchElementException e) {
            System.out.println("NoSuchElementException");
            Reporter.log("NoSuchElementException<br/>");
            if(attempts==9){
                throw(e);

            }
        }
        catch(StaleElementReferenceException e) {
            System.out.println("StaleElementReferenceException");
            Reporter.log("StaleElementReferenceException<br/>");
            if(attempts==9){
                throw(e);
            }
        }}

これにより、 NoSuchElementException と StaleElementReferenceException が発生するのを防ぎ、非常にうまく機能します。

私の最初の質問は、このアプローチが正しいかどうかです。2番目の最も重要な質問は、時々次の問題が発生することです。

Testng は「clickSaveButton」(最終レポート) が渡されたと言っていますが、実際には clickSaveButton アクションは発生しませんでした (テスト中にブラウザを見ているとわかります)。次のテストの最後に、「NoSuchElementException」があります(特に、次のテストが何かをクリックするのではなく、html コンポーネントからテキストを取得するだけの場合)。もちろん、この NoSuchElementException が発生するのは、探している要素が実際には存在しないためです (最後のテスト アクションが発生しなかったため、この要素がなくても前のサイトにいるためです) この状況が発生する理由を教えてください (常に重要であるとは限りません)しかし、たまにしかありません)そしてそれを防ぐ方法は?

前もって感謝します。

4

4 に答える 4

1

ありがとうございました。私がテストしていたアプリケーションに popup winowow のようなものがあったために私の問題が発生したことが判明しました(正確には richFaces rich:modalPanel )。そのため、このポップアップの「背後」にある DOM は引き続き表示されていましたが、そのため、その中の要素はクリックできませんでした。私の問題を解決したのは、要素が ExpectedConditions.elementToBeClickable(By by) を介してクリック可能になるのを少し待って、ポップアップを閉じて別の要素をクリックできるようにしたことです。それが Ardesco の答えです。もう一度ありがとう。

于 2013-03-22T08:58:22.093 に答える
1

明示的な待機を使用して、要素が表示されるまで待機することをお勧めします。これは WebDriverWait で行われます。これにより、コードが次のように変更されます。

public void clickSaveButton(WebDriver driver){
    Configuration.clickfoundElement(By.id(conf.get("saveButton")), driver);
}

これに:

public void clickSaveButton(WebDriver driver) {
    WebDriverWait doWait = new WebDriverWait(driver, 15 , 100);
    WebElement elementToClick = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(conf.get("saveButton"))));
    elementToClick.click();
}

また、clickfoundElement() メソッドを完全に取り除きます。これは、StaleElementExceptions の発生を止めるものではありません。StaleElementException は、DOM が変更され、対話する要素が破棄されてから再作成されることによって発生します。

StaleElementExceptions を回避するには、いくつかのオプションがあります。

  1. ロケータを使用するたびに、常にロケータを使用して要素を見つけてください。
  2. サポートで PageFactory クラスを使用します。

私はすべてのテスト コードで PageFactory を個人的に使用しています。基本的な例は次のようになります。

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;

public class LoginExample {

  @FindBy(how = How.ID, using = "username")
  private WebElement usernameField;
  @FindBy(how = How.ID, using = "password")
  private WebElement passwordField;
  @FindBy(how = How.ID, using = "login")
  private WebElement submitButton;

  public LoginExample(WebDriver driver) {
    PageFactory.initElements(driver, this);
  }

  public void enterCredentialsAndSubmitForm(String username, String password) {
    usernameField.clear();
    usernameField.sendKeys(username);
    passwordField.clear();
    passwordField.sendKeys(password);
    submitButton.click();
  }
}

@FindBy アノテーションは効果的にプロキシ WebElement を作成します。この WebElement を使用するたびに、アノテーションで指定されたロケーターを使用して再度検索されるため、StaleElementException エラーは発生しません (要素が数ミリ秒で変更されるほど運が悪い場合を除きます)。 Selenium がそれを見つけて、それに対してアクションを実行します)。

上記の例では、コンストラクターでページ ファクトリを初期化することでごまかしています。この方法で行う必要はありませんが、一般的には、この方法が適切で簡単な方法であることがわかります。

ページ ファクトリ Java の詳細については、Selenium Wikiを参照してください。

于 2013-03-15T09:08:47.727 に答える
0

By変数を作成し、その変数をページオブジェクトの次のメソッドに次のように渡すことで問題を解決できると思います。

By saveButton = By.id("saveButton");

public By getSaveButton() {
  waitForElementPresent(saveButton, 15);
  return driver.findElement(saveButton);
}

public void waitForElementPresent(final By locator, int timeout) {
  ExpectedCondition e = new ExpectedCondition<Boolean>() {
    public Boolean apply(WebDriver driver) {
      return driver.findElements(locator).size() > 0;
    }
  };

  WebDriverWait wait = new WebDriverWait(driver, timeout);
  wait.until(e);

}

期待される状態を希望の状態に変更することができます。次に、テストで、保存ボタンをクリックします。

page.getSaveButton().click();

IE8でクリック()が発生しないことに関しては、RemoteWebDriverでも同様の動作が見られます。click()が正しく起動されない理由の1つはこれであると思われるため、Webドライバーに正しいズーム設定があることを確認してください。一部の人々はこれを数回クリックすることで解決したようですが、これは汚い解決策のようです。IE7、8、9のclick()の解決策は、実際のonclickjavascript関数を次のように実行することでした。 ((JavaScriptExecutor)driver).executeScript("onclickFunction();");

これは、javascript関数をonclickで呼び出す必要があるというテストではなく、javascript関数がページに要素を動的に追加することをテストするためにのみ受け入れられました。

StaleElementReferenceExceptionに関しては、各テストで新しいページオブジェクトをインスタンス化します。これにより、古い要素を取得せず、クリーンな状態から開始できます。JUnit4では、これは@Beforeメソッドに含まれます。

于 2013-03-20T13:37:19.737 に答える
0

while ループで試行変数をインクリメントしていません。適切なアプローチはわかりませんが、while ループを使用して要素を検索することはありません。driver.findElements()代わりにdriver.findElement()使用して、いくつかのアサーションを使用する必要があるかもしれません。たとえば、ボタンが本当にそこにあるかどうかを確認してみてください。

于 2013-03-15T07:59:07.877 に答える