2012-10-22 5 views
15

における二つの要素のいずれかを見つけるdriver.findElement(By.id("idA"))私のアプリケーションでwebdriverを

webdriverにAまたはBのいずれかを検索するにはどうすればよいですか?

あり、少なくとも一つの要素が見つかったときに待って停止します方法driver.findElements(By)があるが、この方法は確実にAかのどちらかを見つけるための適切な方法は何ですかAとB

に同じロケータを使用するように私を強制的にB、暗黙のタイムアウトを待つ必要はありませんか?

+0

Iは 'driver.findElements(By.cssSelector(「[ID = A] [ID = Bとビット遊ん] "))'それは*や*ではありません。私はCSS *セレクターを見つけられませんでした。 – VolkerK

答えて

17

のid I2とのid I1または要素と要素

のxpath://E1[@id=I1] | //E2[@id=I2]

CSS:css=E1#I1,E2#I2

driver.findElement(By.xpath(//E1[@id=I1] | //E2[@id=I2])) 
driver.findElement(By.cssSelector(E1#I1,E2#I2)) 

がfluentWaitメカニズムを忘れないでください:

public WebElement fluentWait(final By locator){ 

     Wait<WebDriver> wait = new FluentWait<WebDriver>(driver) 
       .withTimeout(30, TimeUnit.SECONDS) 
       .pollingEvery(5, TimeUnit.SECONDS) 
       .ignoring(org.openqa.selenium.NoSuchElementException.class); 

     WebElement foo = wait.until(
       new Function<WebDriver, WebElement>() { 
        public WebElement apply(WebDriver driver) { 
         return driver.findElement(locator); 
        } 
       } 
     ); 
     return foo; 
}; 

あなたはfluentWaitについてもっと詳しく知ることができますFYI

fluentWait(By.xpath(//E1[@id=I1] | //E2[@id=I2])); 
fluentWait(By.cssSelector(E1#I1,E2#I2)) 

:あなたの問題へ

IMHOソリューションは次のようになりhereこれはあなたを助けcssSelectorマニュアル

希望、素敵なXPathのです。うまくFluentWait上のご質問に関する

+0

xpath ORオペランドを使用したアプローチは、魅力的に機能しました!最初にこれらの要素のどれかを見つけ、 'element.getAttribute(" id ")'をチェックして、実際に見つかったものを見つけます。ありがとうございました!ところで、FluentWaitが 'driver.manage()。timeouts()。implicitlyWait(20、TimeUnit.SECONDS);'によって設定されたデフォルトの暗黙的タイムアウトをオーバーライドできることを正しく理解していますか? –

+0

あなたはどのwebdriverのバージョンを使用していますか? 2.22 'driver.findElement(By.cssSelector(E1#I1、E2#I2))'が例外に繋がるorg.openqa.selenium.WebDriverException:コンパウンドセレクタが許可されていません – VolkerK

+0

はもう一つの答えをfluentWaitに追加しました –

0

@pavel_kazlou、:基本的に待ち時間の2つのタイプがあります。 明示的な待機

WebDriverWait.until(condition-that-finds-the-element) 

暗黙の待ち時間が

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 

違いは

です
    明示的にあなたが状態をチェックする頻度(代わりに500 ミリ秒の)、設定することができ
  • のみ、特定の要素のための暗黙の待機時間があなたの スクリプト内のすべての要素に適用されるが、明示された - 明白な10
  • "NoSuchElement"以外の例外を無視するように設定することもできます。 WebDriverWait(FluentWaitを拡張)と同様に動作するFluentWaitを使用しますが、少し柔軟性があります。

ここではWebDriverWaitの使用例を示します(要素のポーリング間隔を指定するには別のWebDriverWaitコンストラクタを使用します(ミリ秒単位)。):具体的には無視するwebdriverを例外を選択する能力を:実際にFluentWaitを拡張WebDriverWait(と同様に動作します)が、あなたは少しより多くの柔軟性を提供しますFluentWaitを使用して

new WebDriverWait(webDriver(), 10, 50).until(ExpectedConditions.elementToBeClickable(By.xpath(menuItemXpath))); 

。 使用例:

new FluentWait(webDriver()) 
.withTimeout(timeout, TimeUnit.SECONDS) 
.pollingEvery(50, TimeUnit.MILLISECONDS) 
.ignoring(NoSuchElementException.class) 
.until(ExpectedConditions.elementToBeClickable(By.xpath(menuItemXpath))); 

私のノートを締結する:fluentWaitが待機の明示的な型であるとあなたに暗黙の待ち時間が待機する時間の一定量を含む場合として、無視するwebdriverを例外の種類を明示的に選択する可能性を提供任意のwebElementに対してこのような観点から、IMHOの流動的アプローチはより強固です。

2

ここに私の解決策があります。これは、他の人が示唆しているように流暢な待ち時間を使います。 getDriver()への呼び出しやドライバへの参照を、ドライバオブジェクトまたはそれをフェッチする独自のメソッドで置き換える必要があります。

/** 
* Waits for any one of a given set of WebElements to become displayed and 
* enabled. 
* 
* @param locators 
*   An array of locators to be sought. 
* @param timeout 
*   Timeout in seconds. 
*/ 
protected void waitForOneOfManyToBePresent(By[] locators, int timeout) { 
    try { 
     (new WebDriverWait(getDriver(), timeout)) 
      .until(somethingIsPresent(locators)); 
    } catch (TimeoutException timeoutEx) { 
     // Do what you wish here to handle the TimeoutException, or remove 
     // the try/catch and let the TimeoutException fly. I prefer to 
     // rethrow a more descriptive Exception 
    } 
} 

/** 
* Condition for presence of at least one of many elements. 
* 
* @param locators 
*   An array of By locators to be sought. 
* @return Boolean T if at least one element is present, F otherwise. 
*/ 
protected ExpectedCondition<Boolean> somethingIsPresent(By[] locators) { 
    final By[] finalLocators = locators; 
    return new ExpectedCondition<Boolean>() { 
     public Boolean apply(WebDriver driver) { 
      boolean found = false; 
      for (By locator : finalLocators) { 
       if (isElementPresent(locator)) { 
        found = true; 
        break; 
       } 
      } 
      return new Boolean(found); 
     } 
    }; 
} 

/** 
* Similar to does element exist, but also verifies that only one such 
* element exists and that it is displayed and enabled. 
* 
* @param by 
*   By statement locating the element. 
* @return T if one and only one element matching the locator is found, and 
*   if it is displayed and enabled, F otherwise. 
*/ 
protected boolean isElementPresent(By by) { 
    // Temporarily set the implicit timeout to zero 
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS); 
    // Check to see if there are any elements in the found list 
    List<WebElement> elements = driver.findElements(by); 
    boolean isPresent = (elements.size() == 1) 
      && elements.get(0).isDisplayed() && elements.get(0).isEnabled(); 
    // Return to the original implicit timeout value 
    driver.manage().timeouts() 
       .implicitlyWait(Properties.TIMEOUT_TEST, TimeUnit.SECONDS); 
    // Properties.TIMEOUT_TEST is from other personal code, replace with your 
    // own default timeout setting. 
    return isPresent; 
} 

私のバージョンはまた、任意の見つかった要素は、単数表示され、有効になっていることを確認するためにチェックし、しかし、あなたのロケータがある場合は、あなたが気にしないならば、あなたは唯一の存在を確認したい場合は簡単にそれを削除したりすることができます複数の一致要素を見つける。デフォルトのタイムアウトを抑制してfindElements()を呼び出すことで要素の有無をチェックするのは難しいかもしれませんが、明らかにSelenium APIで推奨される方法です。

2

私はこのためにExpectedConditionを書きました。

public static ExpectedCondition<By> titleIs(final By[] selectors) { 
    return new ExpectedCondition<By>() { 
     public By apply(WebDriver driver) { 
      WebElement el=null; 
      for (By selector:selectors) { 
       try { 
        el = driver.findElement(selector); 
       } catch (NoSuchElementException ex) { 
        // ignore as we are waiting for that to stop 
       } 
       if (el!=null) return selector; 
      } 
      return null; 
     } 
    }; 
} 
1

私はこの問題にも遭遇しましたので、私はその方法を作りました。 このメソッドは、webdriverが "self._driver"というクラス内にあることに注意してください。コードはPythonで書かれています。

メソッドを呼び出すの例は次のようになります

self.MES(3、( '名前'、 'name_of_element1')、( 'ID'、 'id_of_element2'))

from selenium.common.exceptions import NoSuchElementException 
import time 

def MES(self, wait_time, element1, element2): 
    ''' 
    A function to check a website for multiple elements at the same time 
    MultiElementSearch. Returns the element if found, or False if neither 
    are found. 
    It will also throw a ValueError is the element locator type is not 
    valid. 

    MES(int, (str, str), (str, str)) -> Element or bool 
    ''' 
    time1 = time.time() 
    while time.time() < (time1 + wait_time): 
     try: 
      if element1[0] == 'id': 
       selection1 = self._driver.find_element_by_id(element1[1]) 
      elif element1[0] == 'name': 
       selection1 = self._driver.find_element_by_name(element1[1]) 
      elif element1[0] == 'xpath': 
       selection1 = self._driver.find_element_by_xpath(element1[1]) 
      elif element1[0] == 'link_text': 
       selection1 = self._driver.find_element_by_link_text(element1[1]) 
      elif element1[0] == 'partial_link_text': 
       selection1 = self._driver.find_element_by_partial_link_text(
        element1[1]) 
      elif element1[0] == 'tag_name': 
       selection1 = self._driver.find_element_by_tag_name(element1[1]) 
      elif element1[0] == 'class_name': 
       selection1 = self._driver.find_element_by_class_name(
        element1[1]) 
      elif element1[0] == 'css_selector': 
       selection1 = self._driver.find_element_by_css_selector(
        element1[1]) 
      else: 
       raise ValueError(
        'The first element locator type is not vaild') 
      return selection1 

     except NoSuchElementException: 
      pass 

     try: 
      if element2[0] == 'id': 
       selection2 = self._driver.find_element_by_id(element2[1]) 
      elif element2[0] == 'name': 
       selection2 = self._driver.find_element_by_name(element2[1]) 
      elif element2[0] == 'xpath': 
       selection2 = self._driver.find_element_by_xpath(element2[1]) 
      elif element2[0] == 'link_text': 
       selection2 = self._driver.find_element_by_link_text(element2[1]) 
      elif element2[0] == 'partial_link_text': 
       selection2 = self._driver.find_element_by_partial_link_text(
        element2[1]) 
      elif element2[0] == 'tag_name': 
       selection2 = self._driver.find_element_by_tag_name(element2[1]) 
      elif element2[0] == 'class_name': 
       selection2 = self._driver.find_element_by_class_name(
        element2[1]) 
      elif element2[0] == 'css_selector': 
       selection2 = self._driver.find_element_by_css_selector(
        element2[1]) 
      else: 
       raise ValueError(
        'The second element locator type is not vaild') 
      return selection2 
     except NoSuchElementException: 
      pass 
    return False 
0

ここにはJava 8ソリューションがあります。

ラッパー・オブジェクト:

import org.openqa.selenium.By; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.ui.ExpectedCondition; 
import org.openqa.selenium.support.ui.Wait; 
import org.openqa.selenium.support.ui.WebDriverWait; 

public class SelectorWebElement 
{ 
    private WebElement webElement; 
    private By by; 

    private SelectorWebElement(WebElement webElement, By by) 
    { 
     this.webElement = webElement; 
     this.by = by; 
    } 

    public By getBy() 
    { 
     return by; 
    } 

    public WebElement getWebElement() 
    { 
     return webElement; 
    } 

    private static ExpectedCondition<SelectorWebElement> findFirstElement(By... selectors) 
    { 
     return driver -> 
     { 
      for (By selector : selectors) 
      { 
       try 
       { 
        assert driver != null; 
        WebElement webElement = driver.findElement(selector); 
        if (webElement.isDisplayed()) 
        { 
         return new SelectorWebElement(webElement, selector); 
        } 
       } catch (Exception ignored) 
       { 

       } 
      } 

      return null; 
     }; 
    } 

    public static SelectorWebElement waitForFirstElement(WebDriver driver, 
                 long timeout, 
                 By... selectors) 
    { 
     Wait wait = new WebDriverWait(driver, timeout); 
     return (SelectorWebElement) wait.until(findFirstElement(selectors)); 
    } 
} 

例コード:

By badPasswordSelector = By.cssSelector("..."); 
By myAccountPage = By.cssSelector("..."); 
SelectorWebElement selectorWebElement = SelectorWebElement.waitForFirstElement(driver, 5, badPasswordSelector, myAccountPage); 

By matchedSelector = selectorWebElement.getBy(); 

if (matchedSelector.equals(badPasswordSelector)) 
{ 
    System.out.println("Bad password"); 
} else if (matchedSelector.equals(myAccountPage)) 
{ 
    System.out.println("Successfully logged in"); 
} 
関連する問題