2012-10-05 8 views
5

次のコードを使用して不在の要素をチェックした場合:セレン2 - 暗黙のうちに要素が存在しないかどうかをチェックする方法?

// ... 
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); 
try { 
    driver.findElement(By.cssSelector("td.name")); 
} catch (NoSuchElementException e) { 

    // here you go, element not found 

} 

あなたは正しい結果を得るが、実行している時間が原因findElementメソッドは暗黙の待ち時間でブロックに、常に30秒です。

暗黙の待機を維持しながら、この動作を回避する方法はありますか?

<EDIT>テストは、非開発者がセレンIDEによって生成されようとしているので、私はできるだけ簡単に自分の仕事を続けるソリューション必要があります(つまり、暗黙の待機を保っていますが!)。 </EDIT>

おかげで、

マルコ

+0

暗黙的な待機を何か小さなものに設定し、その後30秒に戻すことができますか? – Arran

+0

Selenium IDEで書かれたテストケースを変換するためのテンプレートを使用していますが、コードの変更を最小限に抑えたいと思っていましたが、暗黙のうちに完全に削除したいと思うでしょう。 –

答えて

2

あなたは、XPathセレクタでそれを行うことができるかもしれません。あなたがそこにいるはずの要素の直前にある要素を見つけて、「次の兄弟」を使って次の要素を取得します。次のようなものがあります。

//td.previous/following-sibling::td 

次に、「名前」が返されていないことを確認します。もちろん、それは別の "td"要素がある場合にのみ機能します。

個人的に私は暗黙の待ちを落として、必要なときだけ待機させたいと思うでしょう。

private WebElement cssWait(final String css) 
{ 
    return new WebDriverWait(driver, 30).until(new ExpectedCondition<WebElement>() 
    { 
     @Override 
     public WebElement apply(WebDriver d) 
     { 
      return d.findElement(By.cssSelector(css)); 
     } 
    }); 
} 
+0

+1は巧妙な解決策です。残念ながら...編集を参照してください –

2

タイムアウトを設定する代わりに、2.25で導入されたfluentWaitを使用します。

public void waitForElement(WebDriver driver, final String xpath) 
{ 
//Set up fluentWait to wait for 35 seconds polling every 1 
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver) 
    .withTimeout(35, TimeUnit.SECONDS) 
    .pollingEvery(1, TimeUnit.SECONDS) 
    .ignoring(NoSuchElementException.class); 

WebElement element; 

//Look for element, if not found start fluentWait 
try 
{ 
    element = driver.findElement(By.xpath(xpath)); 
} 
catch (WebDriverException e) 
{ 
    logger.info("[getElementByXpath] Element not initially found. Starting fluentWait ["+xpath+"]"); 

    try 
    { 
     element = fluentWait.until(new Function<WebDriver, WebElement>() { 
      public WebElement apply(WebDriver d) { 

       return d.findElement(By.xpath(xpath)); 
      } 
     }); 
    } 
    catch (WebDriverException f) 
    { 
     logger.info("[getElementByXpath] FluentWait findElement threw exception:\n\n" + f +"\n\n"); 

     throw new WebDriverException("Unable to find element ["+xpath+"]"); 
    } 
} 

//Once we've found the element wait for element to become visible 
fluentWait.until(ExpectedConditions.visibilityOf(element)); 
} 

あなたはこのような何かにあなたの方法を変換した場合、あなたは即座に要素を見つける「未」することができ、あなたのdriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);を削除することができるだろう。

希望すると便利です。

+0

それは私が通常行く方法です、ありがとう。 Alas ...編集を参照してください。 –

3

上記の方法は、要素がもはや存在しなくても、指定された時間だけ待機します。私は、要素が見え、存在しないまで待つための独自のメソッドを書いていました。彼らは私のために働く。ここで彼らは、次のとおりです。

public void waitUntilElementExists(By by, int waitSeconds, 
     int noOfRetries) { 
    getDriver().manage().timeouts().implicitlyWait(waitSeconds, TimeUnit.SECONDS); 
    boolean foundElement = false; 
    for (int i = 0; i < noOfRetries; i++) 
     try { 
      getDriver().findElement(by); 
      foundElement = true; 
      break; 
     } catch (Exception e) { 
     } 
    assertTrue("The searched element was not found after " + noOfRetries * waitSeconds + " seconds!", foundElement); 
} 

public void waitUntilElementDoesntExist(By by, int waitSeconds, 
     int noOfRetries) { 
    getDriver().manage().timeouts().implicitlyWait(waitSeconds, TimeUnit.SECONDS); 
    boolean elementDisappeared = false; 
    for (int i = 0; i < noOfRetries; i++) 
     try { 
      getDriver().findElement(by); 
      waitABit(1000 * waitSeconds); 
     } catch (Exception e) { 
      elementDisappeared = true; 
      break; 
     } 
    assertTrue("The searched element did not disappear after " + noOfRetries * waitSeconds + " seconds!", elementDisappeared); 
} 
0

あなたはfindElementsを、使用しています。このような機能を、必要はありませfindElement

その後
public static ExpectedCondition<Boolean> elementCountIs(final By sel, final int count) { 
    return new ExpectedCondition<Boolean>() { 
     public Boolean apply(WebDriver driver) { 
      return driver.findElements(sel).size() == count; 
     } 
    }; 
} 

Falkenfighterによって記述として、あなたがFluentWaitオブジェクトを設定することができます。

fluentWait.until(elementCountIs(By.cssSelector("td.name"), 0); 
+0

申し訳ありませんが、私は今これが間違っていることを認識しました。暗黙の待機は、findElementと同じくらい多くのfindElementに適用されます。これは非常に面倒です。 –

0

一時的にImplicitWaitを更新し、完了後にImplicitWaitをリセットする必要があります。

この状況を処理した方法です。現在のデフォルトを保存し、ImplicitWaitを一時的に更新してから、デフォルトに戻します。 https://blog.mozilla.org/webqa/2012/07/12/webdrivers-implicit-wait-and-deleting-elements/

public bool ElementExists(By by, int waitMilliseconds) 
{ 
     var defaultWebDriverTimeout = 30000;// Get default timeout that you're using 
     WebDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(waitMilliseconds)); 

     try 
     { 
      WebDriver.FindElement(by); //Note could be FindElements instead, but this is quicker 
      return true; 
     } 
     catch (NoSuchElementException) 
     { 
      return false; 
     } 
     finally 
     { 
      WebDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(defaultWebDriverTimeout)); 
     } 
} 
0

いいえ、あなたはできません:
これは、彼らはあなたが存在していないに何かを期待している。このような状況を処理する方法であるMozillaの提案を、オフに基づいています。 implicit明示的な待機よりも待機時間が優先されます。 implicitの時間が30秒の場合、要素が存在しない場合は少なくとも30秒後に実行されます。 フレームワークの待ち時間をimplicitにすることはできますが、IDEとの関係はわかりません。

booleanの結果を返すカスタムメソッドを作成しました。 入力はロケータWebDriver(CSS、xpathなど)でサポートされています。 または、好きなように変更することができます。

これは、私のコードをよりきれいに素早くするのに役立ちました。他の人にも役立つことを願っています。

デフォルトのpoolingは500ミリリスですが、waitオブジェクトで変更できます。

public boolean isElementNotPresent(final By locator) { 
     boolean result = false; 
     // use your custom timeout here 
     long timeout = ConfigurationProvider.getWebDriverWaitTimeout(); 

     // log4j used 
     msg = "isElementNotPresent: " + locator; 
     LOG.info(msg); 

     Wait<WebDriver> wait = new FluentWait<WebDriver>(
       getDriver()).withTimeout(timeout, TimeUnit.SECONDS); 

     try { 
      result = wait.until(new Function<WebDriver, Boolean>() { 
       @Override 
       public Boolean apply(WebDriver driver) { 
        return driver.findElements(locator).size() == 0; 
       } 
      }); 
     } catch (TimeoutException e) { 
      msg = String.format("Element remained visible after %.2f seconds", 
      ((float) timeout/1000)); 
      LOG.debug(msg); 
     } catch (Exception e) { 
      msg = "Exception at isElementNotPresent()\n" + e.getMessage(); 
      // I use jUnit to fail my test 
      Assert.fail(msg); 
     } 

     return result; 
    }; 
関連する問題