2012-10-22 26 views
15

में दो तत्व अपने आवेदन में से किसी को खोजने जब मैं खोलने पेज इलेवन या तो तत्व एक या तत्व बी वे डोम में विभिन्न स्थानों में रखा जाता है और उनके आईडी का उपयोग कर पाया जा सकता है देखने की उम्मीद उदाहरण के लिए, driver.findElement(By.id("idA"))webdriver

मैं ए या बी खोजने के लिए वेबड्राइवर से कैसे पूछ सकता हूं?

विधि driver.findElements(By) जो जब कम से कम एक तत्व पाया जाता है इंतज़ार कर बंद हो जाएगा नहीं है, लेकिन इस विधि मुझे मजबूर करता एक के लिए एक ही लोकेटर उपयोग करने के लिए और बी

मज़बूती से या तो एक या खोजने के लिए उचित तरीका क्या है बी, ताकि मुझे अंतर्निहित टाइमआउट का इंतजार नहीं करना पड़े?

+0

मैं 'साथ driver.findElements (By.cssSelector (" [id = एक] [id = ख चारों ओर एक सा खेला ] ")) 'लेकिन यह एक * या * नहीं है। मुझे एक सीएसएस * या * चयनकर्ता नहीं मिला है। Xpath या operand का उपयोग कर – VolkerK

उत्तर

17
आईडी I1 या आईडी I2 साथ तत्व के साथ

तत्व

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

सीएसएस: 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के बारे में अधिक जानकारी प्राप्त कर सकते हैं आपकी समस्या को

IMHO समाधान हो जैसे:

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

FYI करें: here अच्छा xpath, cssSelector मैनुअल

आशा है कि यह आप में मदद करता है।

+0

दृष्टिकोण एक आकर्षण की तरह काम किया! सबसे पहले मुझे उन तत्वों में से कोई भी मिलता है और फिर मुझे यह पता लगाने के लिए 'element.getAttribute ("id")' जांचें कि मुझे वास्तव में कौन सा मिला। धन्यवाद! वैसे, क्या मैं सही ढंग से समझता हूं कि FluentWait 'driver.manage()। Timeouts() द्वारा निर्धारित डिफ़ॉल्ट निहित टाइमआउट को ओवरराइड करने की अनुमति देता है। ImplicitlyWait (20, TimeUnit.SECONDS);'? –

+0

आप किस वेबड्राइवर संस्करण का उपयोग कर रहे हैं? 2.22 'driver.findElement (By.cssSelector (E1 # I1, E2 # I2) के साथ) 'अपवाद की ओर ले जाता है' org.openqa.selenium.WebDriverException: कंपाउंड चयनकर्ताओं को अनुमति नहीं है ' – VolkerK

+0

फ़्लेंट Wait –

0

@pavel_kazlou, अच्छी तरह से FluentWait पर अपने प्रश्न के विषय में: मूल रूप से वहाँ प्रतीक्षा के दो प्रकार हैं: स्पष्ट इंतजार

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

अंतर्निहित इंतजार

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

अंतर

है
  • स्पष्ट - आपके स्क्रिप्ट के सभी तत्वों पर लागू प्रतीक्षा समय लागू होता है लेकिन केवल विशेष तत्व
  • स्पष्ट रूप से स्पष्ट रूप से आप कॉन्फ़िगर कर सकते हैं, कितनी बार (500 मिलीसेकंड के बजाय) आप स्थिति की जांच करना चाहते हैं।
  • स्पष्ट में आप भी समय समाप्ति तक "NoSuchElement" के अलावा अन्य अपवादों को अनदेखा करने की .. एक FluentWait जो WebDriverWait (जो वास्तव में FluentWait फैली) की तरह ही काम करता है, लेकिन आप एक छोटे से अधिक लचीलापन प्रदान करता प्रयोग करें कॉन्फ़िगर कर सकते हैं।

यहां वेबड्राइवरवाइट उपयोग उदाहरण है (तत्व मतदान मतदान अंतराल (मिलीसेकंड में मापा गया) निर्दिष्ट करने के लिए एक अलग WebDriverWait कन्स्ट्रक्टर का उपयोग करें।):

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

एक FluentWait जो इसी तरह WebDriverWait (जो वास्तव में FluentWait फैली करने के लिए काम करता है) लेकिन आप एक छोटे से अधिक लचीलापन प्रदान करता है का उपयोग करना: अनदेखी करने के लिए WebDriver अपवाद का चयन करने की क्षमता विशेष रूप से। के उपयोग का उदाहरण:

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

मेरी टिप्पणी निष्कर्ष करने के लिए: fluentWait इंतजार का एक स्पष्ट प्रकार है और आप संभावना स्पष्ट रूप से चयन करने के लिए WebDriver अपवाद की किस प्रकार की अनदेखी करने, जहां प्रतीक्षा करने के रूप में किसी भी अंतर्निहित प्रतीक्षा समय की निश्चित राशि भी शामिल है प्रदान करता है किसी भी वेबलेमेंट के लिए। IMHO fluentWait दृष्टिकोण इस दृष्टिकोण से अधिक मजबूत है।

2

यहां मेरा समाधान है, जो दूसरों के सुझाव के अनुसार एक धाराप्रवाह प्रतीक्षा का उपयोग करता है। आपको ड्रायवर() या चालक ऑब्जेक्ट के साथ किसी ड्राइवर को संदर्भ या किसी भी कॉल को बदलने के लिए किसी भी कॉल को प्रतिस्थापित करने की आवश्यकता होगी।

/** 
* 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() को कॉल करना प्रतीत होता है, लेकिन यह स्पष्ट रूप से सेलेनियम एपीआई में ऐसा करने का अनुशंसित तरीका है।

2

मैंने एक अपेक्षित कंडिशन लिखा था जिसके लिए इसका उपयोग करने में स्वतंत्र महसूस होता है।

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

मैं इस समस्या से भी आया क्योंकि मैंने इसके लिए एक विधि भी बनाई। कृपया ध्यान दें कि विधि उस वर्ग के अंदर बैठती है जिसमें वेबड्राइवर "self._driver" होता है। कोड पायथन में है।

विधि बुला का एक उदाहरण होगा:

self.MES (3, ('नाम', 'name_of_element1'), ('आईडी', '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"); 
} 
संबंधित मुद्दे