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


100

मैं एक जावा सेलेनियम-वेबड्राइवर पर काम कर रहा हूं। मैंने कहा

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

तथा

WebElement textbox = driver.findElement(By.id("textbox"));

क्योंकि मेरे एप्लिकेशन को उपयोगकर्ता इंटरफ़ेस लोड करने में कुछ सेकंड लगते हैं। इसलिए मैंने 2 सेकंड इंक्विविविट सेट किया। लेकिन मैं तत्व टेक्स्टबॉक्स का पता लगाने में असमर्थ रहा

फिर मैं जोड़ता हूं Thread.sleep(2000);

अब यह ठीक काम करता है। कौन सा बेहतर तरीका है?


जवाबों:


123

वैसे, दो प्रकार के प्रतीक्षा हैं: स्पष्ट और अंतर्निहित प्रतीक्षा। स्पष्ट प्रतीक्षा का विचार है

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

निहित प्रतीक्षा की अवधारणा है

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

आप यहाँ विवरण में अंतर पा सकते हैं

ऐसी स्थितियों में मैं स्पष्ट प्रतीक्षा ( fluentWaitविशेष रूप से) का उपयोग करना पसंद करूंगा :

public WebElement fluentWait(final By locator) {
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);

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

    return  foo;
};

fluentWaitफ़ंक्शन आपके पाया गया वेब तत्व देता है। प्रलेखन सेfluentWait : प्रतीक्षा इंटरफ़ेस का कार्यान्वयन जो कि उड़ान के समय कॉन्फ़िगर किया गया और मतदान का अंतराल हो सकता है। प्रत्येक फ्लुएंटविट उदाहरण एक शर्त के लिए प्रतीक्षा करने के लिए अधिकतम समय निर्धारित करता है, साथ ही आवृत्ति जिसके साथ स्थिति की जांच करना है। इसके अलावा, उपयोगकर्ता प्रतीक्षा को कॉन्फ़िगर कर सकता है विशेष प्रकार के अपवादों की प्रतीक्षा करते हुए, जैसे कि NoSuchElementException जब पृष्ठ पर एक तत्व खोज रहा हो। विवरण आप यहां प्राप्त कर सकते हैं

का उपयोग fluentWaitआपके मामले में निम्नलिखित हैं:

WebElement textbox = fluentWait(By.id("textbox"));

यह दृष्टिकोण IMHO बेहतर है क्योंकि आप नहीं जानते कि कितना समय इंतजार करना है और मतदान अंतराल में आप मनमाने ढंग से समय निर्धारित कर सकते हैं कि किस तत्व की उपस्थिति के माध्यम से सत्यापित किया जाएगा। सादर।


3
वह import com.google.common.base.Function;नहीं,import java.util.function.Function;
haventchecked

haventchecked, वास्तव में intelij IDEA का उपयोग विकास के लिए कर रहा है, यह ऑटो-आयात (जब
मावेन

1
मैं बस दूसरों को कॉल कर रहा था जो सोच रहे होंगे कि Functionइसका इस्तेमाल किया जा रहा है। यह मेरे लिए पहले स्पष्ट नहीं था। जवाब के लिए धन्यवाद।
haventchecked

1
या आप सिर्फ एक लंबोदर अभिव्यक्ति का उपयोग कर सकते हैं driver -> driver.findElement(locator):। इसका उपयोग करते समय आपको आयात विवरण की आवश्यकता नहीं होगी।
थिबस्टार्स

2
अब यह है: .withTimeout(Duration.ofSeconds(30)).pollingEvery(Duration.ofSeconds(5))के स्थान पर: .withTimeout(30, TimeUnit.SECONDS).pollingEvery(5, TimeUnit.SECONDS)
SuperRetro

16

यह धागा थोड़ा पुराना है, लेकिन मुझे लगा कि मैं वर्तमान में क्या करूंगा (कार्य प्रगति पर है)।

हालाँकि, मैं अभी भी उन स्थितियों से जूझ रहा हूँ जहाँ सिस्टम भारी लोड के अधीन है और जब मैं सबमिट बटन पर क्लिक करता हूँ (जैसे, login.jsp), तो तीनों स्थितियाँ (नीचे देखें) वापसी true लेकिन अगला पृष्ठ (जैसे, home.jsp) hasn ' टी अभी तक लोड करना शुरू कर दिया।

यह एक सामान्य प्रतीक्षा विधि है जो ExpectedConditions की सूची लेती है।

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
    boolean isLoaded = false;
    Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(waitTimeInSec, TimeUnit.SECONDS)
            .ignoring(StaleElementReferenceException.class)
            .pollingEvery(2, TimeUnit.SECONDS);
    for (ExpectedCondition<Boolean> condition : conditions) {
        isLoaded = wait.until(condition);
        if (isLoaded == false) {
            //Stop checking on first condition returning false.
            break;
        }
    }
    return isLoaded;
}

मैंने विभिन्न पुन: प्रयोज्य ExpectedConditions (तीन नीचे हैं) को परिभाषित किया है। इस उदाहरण में, तीन अपेक्षित स्थितियों में document.readyState = 'पूरा', वर्तमान में कोई "Wait_dialog" शामिल है, और कोई 'spinners' (तत्व जो async डेटा का संकेत देने का अनुरोध किया जा रहा है)।

केवल पहले वाले को सभी वेब पेजों पर उदारतापूर्वक लागू किया जा सकता है।

/**
 * Returns 'true' if the value of the 'window.document.readyState' via
 * JavaScript is 'complete'
 */
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
        Boolean result;
        try {
            result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
        } catch (Exception ex) {
            result = Boolean.FALSE;
        }
        return result;
    }
};
/**
 * Returns 'true' if there is no 'wait_dialog' element present on the page.
 */
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
            WebElement wait = driver.findElement(By.id("F"));
            if (wait.isDisplayed()) {
                loaded = false;
            }
        } catch (StaleElementReferenceException serex) {
            loaded = false;
        } catch (NoSuchElementException nseex) {
            loaded = true;
        } catch (Exception ex) {
            loaded = false;
            System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
        }
        return loaded;
    }
};
/**
 * Returns true if there are no elements with the 'spinner' class name.
 */
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
        List<WebElement> spinners = driver.findElements(By.className("spinner"));
        for (WebElement spinner : spinners) {
            if (spinner.isDisplayed()) {
                loaded = false;
                break;
            }
        }
        }catch (Exception ex) {
            loaded = false;
        }
        return loaded;
    }
};

पृष्ठ के आधार पर, मैं उनमें से एक या सभी का उपयोग कर सकता हूं:

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

निम्न वर्ग में पूर्वनिर्धारित अपेक्षित शर्तें भी हैं : org.openqa.selenium.support.ui.ExpectedConditions


1
बहुत बढ़िया जवाब! मैंने कभी नहीं देखा है कि किसी ने विधि निर्माणकर्ता के माध्यम से एक ExpectedCondition आइटम पास किया है। क्या कमाल का तरीका है। +1
djangofan 16

जेफ विंसेंट, क्या आप मुझे बता सकते हैं कि यह कार्य पृष्ठ के लिए 5 मिनट प्रतीक्षा करने के लिए होगा यदि हाँ, तो कृपया सुझाव दें कि किस पैरामीटर को भेजने की आवश्यकता है?
खानम

यह एक बेहतरीन जवाब है। मेरे पास इस तरह के फ़ंक्शन हैं, हालांकि, मुझे इसे हर फ़ंक्शन में कॉल करना होगा ताकि मेरी स्क्रिप्ट पृष्ठ लोड (स्पिनर) तक इंतजार करे। वहाँ तरीका है कि मैं चुपचाप ImplicitWait में इस waForSpinner फ़ंक्शन को हुक कर सकता हूं ताकि मुझे अपने फ़ंक्शन में इसे हर बार कॉल करने की आवश्यकता न हो? फ़ंक्शन को परिभाषित करने की तरह, इसे एक बार ड्राइवर को हुक करें और बूम करें।
भुवनेश मणि

13

यदि webdriverJs (node.js) का उपयोग कर रहे हैं,

driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
    driver.sleep(5000);
});

बटन को क्लिक करने के बाद उपरोक्त कोड 5 सेकंड के लिए ब्राउज़र की प्रतीक्षा करता है।


18
जब यह सवाल विशेष रूप से जावा, नोड / जावास्क्रिप्ट के बारे में नहीं है, तो आप इसे क्यों पोस्ट करेंगे? यह रूबी में कैसे करना है इसका उत्तर देना विषय के रूप में है।
थोरोन्नो

1
नींद का उपयोग करने के लिए सिफारिश निश्चित रूप से एक अच्छा समाधान नहीं है
Kiril S.

@ Thor84no मुख्य रूप से हम में से कुछ लोग वेब समाधान की खोज कर रहे हैं, इस उत्तर को
खोजते हैं

10

उपयोग Thread.sleep(2000);एक बिना शर्त प्रतीक्षा है। यदि आपका परीक्षण तेजी से लोड होता है, तो भी आपको इंतजार करना होगा। तो सिद्धांत रूप में उपयोग implicitlyWaitकरना बेहतर उपाय है।

हालाँकि, मैं यह नहीं देखता कि implicitlyWaitआपके मामले में काम क्यों नहीं होता है। क्या आप मापते हैं कि क्या findElementवास्तव में अपवाद को फेंकने से पहले दो सेकंड लगते हैं। यदि हां, तो क्या आप इस उत्तर में वर्णित वेबड्राइवर के सशर्त प्रतीक्षा का उपयोग करने का प्रयास कर सकते हैं ?


3

मुझे कस्टम स्थितियों का उपयोग करना पसंद है। यहाँ पायथन में कुछ कोड है:

def conditions(driver):
    flag = True
    ticker = driver.find_elements_by_id("textbox")
    if not ticker:
        flag = False
    return flag

... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)

जब भी आपको प्रतीक्षा करने की आवश्यकता होती है, आप एक निश्चित तत्व की मौजूदगी की जांच करके इसे स्पष्ट रूप से कर सकते हैं (ऐसा तत्व पृष्ठ से पृष्ठ पर भिन्न हो सकता है)। find_elements_by_idरिटर्न सूची - खाली है या नहीं, आपको बस जांचना है।


2

क्लिक अवरुद्ध हो रहा है? यदि आप WebDriverJS का उपयोग कर रहे हैं, तो यहां प्रतीक्षा करने का एक और तरीका है:

driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
  driver.getPageSource().then(function(source) {
    console.log(source);
  });
});

बटन को लोड करने के लिए अगले पेज पर क्लिक करने के बाद ऊपर दिए गए कोड को लोड किया जाता है और फिर अगले पेज के स्रोत को पकड़ लेता है।


1
क्या कोड लोड होने के लिए अगले पृष्ठ की प्रतीक्षा करता है? क्या यह है कि कॉलबैक में पहला कॉल getPageSource है?
आइसोक्रोनस

1

Implicitly प्रतीक्षा करें और थ्रेड। स्लीप केवल दोनों ही सिंक्रनाइज़ेशन के लिए उपयोग किए जाते हैं..लेकिन अंतर यह है कि हम पूरे प्रोग्राम के लिए इम्प्लांटली प्रतीक्षा का उपयोग कर सकते हैं, लेकिन थ्रेड। स्लीप केवल उसी कोड के लिए काम करेगा..जब मेरे सुझाव का उपयोग किया जाता है, तो प्रोग्राम में एक बार प्रतीक्षा करें जब हर बार आपका वेबपेज रीफ्रेश हो जाएगा मतलब उस समय थ्रेड.स्लीप का उपयोग करें। यह बहुत बेहतर होगा :)

यहाँ मेरा कोड है:

package beckyOwnProjects;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;

public class Flip {

    public static void main(String[] args) throws InterruptedException {
        WebDriver driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
        driver.get("https://www.flipkart.com");
    WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
    Actions act=new Actions(driver);
    Thread.sleep(5000);
    act.moveToElement(ele).perform();
    }

}

0

कभी-कभी निहित प्रतीक्षा अधिक होने लगती है और प्रतीक्षा समय कम हो जाता है। [@ eugene.polschikov] का व्हिस पर अच्छा प्रलेखन था। मैंने सेलेनियम 2 के साथ अपने परीक्षण और कोडिंग में पाया है कि निहित इंतजार अच्छे हैं लेकिन कभी-कभी आपको स्पष्ट रूप से इंतजार करना पड़ता है।

सोने के लिए सीधे धागे को बुलाने से बचना बेहतर है, लेकिन कभी-कभी इसके आस-पास कोई अच्छा तरीका नहीं होता है। हालांकि, अन्य सेलेनियम भी हैं जो प्रतीक्षा विकल्प प्रदान करते हैं। waitForPageToLoad और waitForFrameToLoad विशेष रूप से उपयोगी साबित हुए हैं।


0

इंप्लिकेट वेट: इंप्लिकेंट वेट के दौरान अगर वेब ड्राइवर अपनी उपलब्धता के कारण इसे तुरंत नहीं ढूंढ पाता है, तो वेबड्राइवर उल्लिखित समय का इंतजार करेगा और यह निर्दिष्ट समय अवधि के दौरान तत्व को फिर से खोजने की कोशिश नहीं करेगा। एक बार निर्दिष्ट समय समाप्त होने के बाद, यह अपवाद को फेंकने से पहले अंतिम बार एक बार फिर से तत्व को खोजने का प्रयास करेगा। डिफ़ॉल्ट सेटिंग शून्य है। एक बार जब हम एक समय निर्धारित करते हैं, तो वेब चालक वेबड्राइवर ऑब्जेक्ट उदाहरण की अवधि की प्रतीक्षा करता है।

स्पष्ट प्रतीक्षा: ऐसे उदाहरण हो सकते हैं जब किसी विशेष तत्व को लोड होने में एक मिनट से अधिक समय लगता है। उस स्थिति में आप निश्चित रूप से इंप्लाट प्रतीक्षा के लिए एक बड़ा समय निर्धारित करना पसंद नहीं करते हैं, जैसे कि यदि आप ऐसा करते हैं तो आपका ब्राउज़र हर तत्व के लिए उसी समय की प्रतीक्षा करने वाला है। उस स्थिति से बचने के लिए आप केवल आवश्यक तत्व पर एक अलग समय लगा सकते हैं। इसका अनुसरण करने से आपका ब्राउज़र निहित प्रतीक्षा समय हर तत्व के लिए कम होगा और यह विशिष्ट तत्व के लिए बड़ा होगा।


0

कभी-कभी निहित प्रतीक्षा विफल हो जाती है, यह कहते हुए कि एक तत्व मौजूद है लेकिन यह वास्तव में नहीं है।

समाधान Driver.findElement का उपयोग करने से बचने के लिए है और इसे एक कस्टम विधि से प्रतिस्थापित करना है जो स्पष्ट रूप से एक स्पष्ट प्रतीक्षा का उपयोग करता है। उदाहरण के लिए:

import org.openqa.selenium.NoSuchElementException;


public WebElement element(By locator){
    Integer timeoutLimitSeconds = 20;
    WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    }
    catch(TimeoutException e){
        throw new NoSuchElementException(locator.toString());
    }
    WebElement element = driver.findElement(locator);
    return element;
}

छिटपुट, सामयिक विफलताओं (इस लिंक को देखें ) के अलावा निहित प्रतीक्षा से बचने के अतिरिक्त कारण हैं ।

आप इस "तत्व" विधि का उपयोग उसी तरह से कर सकते हैं जैसे कि driver.findElement। उदाहरण के लिए:

    driver.get("http://yoursite.html");
    element(By.cssSelector("h1.logo")).click();

यदि आप वास्तव में समस्या निवारण या कुछ अन्य दुर्लभ अवसरों के लिए कुछ सेकंड इंतजार करना चाहते हैं, तो आप सेलेनियम आईडीई के समान एक विराम विधि बना सकते हैं:

    public void pause(Integer milliseconds){
    try {
        TimeUnit.MILLISECONDS.sleep(milliseconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

0

उत्तर : सेलेनियम वेबड्राइवर का उपयोग करके तत्व दृश्यता से पहले कुछ सेकंड प्रतीक्षा करें।

implicitlyWait () : वेबड्राइवर उदाहरण पूर्ण पेज लोड होने तक प्रतीक्षा करें। पूर्ण पृष्ठ लोड की प्रतीक्षा करने के लिए आप 30 से 60 सेकंड का उपयोग करते हैं।

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

स्पष्ट रूप से WebDriverWait () : WebDriver का उदाहरण पूर्ण पृष्ठ लोड होने तक प्रतीक्षा करें।

WebDriverWait wait = new WebDriverWait(driver, 60);

wait.until(ExpectedConditions.visibilityOf(textbox));

driver.findElement(By.id("Year")).sendKeys(allKeys);

नोट : कृपया किसी विशेष WebElement को संभालने के लिए ExplicitlyWait WebDriverWait () का उपयोग करें।



-1

मैं 2 सेकंड के लिए प्रतीक्षा करने के लिए निम्न कोड पसंद करता हूं।

for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
   Thread.sleep(1000);
}

-1
Thread.sleep(1000);

यह बदतर है: एक स्थिर प्रतीक्षा होने के नाते, यह परीक्षण स्क्रिप्ट को धीमा कर देगा।

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

यह एक गतिशील प्रतीक्षा है

  • यह वेबड्राइवर के अस्तित्व तक मान्य है या चालक के जीवनकाल तक इसकी गुंजाइश है
  • हम प्रतीक्षा को भी निहित कर सकते हैं।

अंत में, मेरा सुझाव है कि क्या है

WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);

कुछ पूर्वनिर्धारित शर्तों के साथ:

isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
  • यह गतिशील प्रतीक्षा भी है
  • इसमें इंतजार केवल सेकंड में होगा
  • हमें किसी विशेष वेब तत्व के लिए स्पष्ट प्रतीक्षा का उपयोग करना होगा जिस पर हम उपयोग करना चाहते हैं।

-4
Thread.Sleep(5000);

इससे मुझे मदद मिली लेकिन इंटरप्टेड अपवाद अपवाद का ध्यान रखने की आवश्यकता है। तो बेहतर यह कोशिश और पकड़ने के साथ चारों ओर:

try {
    Thread.Sleep(5000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

या

घोषणाएँ जोड़ें:

public class myClass {
    public static void main(String[] args) throws InterruptedException
    { ... }

मैं दूसरे को पसंद करूंगा क्योंकि एक के बाद एक sleep()जितनी बार चाहें उपयोग कर सकते हैं tryऔर catchहर बार और जहां भी sleep()इस्तेमाल किया गया है, उसके दोहराव से बचें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.