รอให้โหลดหน้าเว็บในซีลีเนียม


240

คุณจะทำให้Selenium 2.0 รอหน้าโหลดได้อย่างไร


7
สำหรับฉันคำตอบของ Paulเท่านั้นที่ถูกต้องคำตอบที่ได้รับการโหวตอย่างสูงส่วนใหญ่พูดถึงการรอองค์ประกอบบางอย่าง
xyz

คำตอบ:


138

คุณสามารถตรวจสอบเจดีย์ด้วยรหัสต่อไปนี้

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));

 wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

22
คุณอาจคิดว่าสิ่งนี้จะถูกสร้างขึ้นการรอให้โหลดหน้าเว็บเป็นสิ่งที่พบได้ทั่วไปบนเว็บ
PRMan

19
มันใช้งานได้จริงตลอดเวลา? อาจจะมีบางอย่างขาดหายไปจากโค้ดของคุณ แต่คุณกำลังรอให้ dom อยู่ในสถานะพร้อม แต่ให้พิจารณาว่าหากโค้ดของคุณรันเร็วเกินไปหน้าก่อนหน้านี้อาจยังไม่ถูกยกเลิกการโหลดและมันจะกลับมาจริงแม้ว่าคุณจะยังอยู่ในหน้าเก่า สิ่งที่คุณต้องทำคือรอให้หน้าปัจจุบันยกเลิกการโหลดแล้วเรียกรหัสข้างต้นของคุณ วิธีในการตรวจสอบการยกเลิกการโหลดหน้าเว็บคือการรับ webelement ในหน้าปัจจุบันและรอจนกว่าจะกลายเป็นค้าง obeythetestinggoat.com/…
จอร์จ

6
FYI - แม้ว่าจะยังไม่ได้รับประกันว่าหน้าจะสมบูรณ์ - เพียงแค่ว่า dom พร้อมใช้งาน dojo / jquery ใด ๆ อาจยังคงสร้างองค์ประกอบแบบไดนามิกบนหน้าดังนั้นคุณอาจต้องรอองค์ประกอบแบบไดนามิกก่อนที่จะโต้ตอบกับพวกเขา
จอร์จ

3
โปรดทราบว่าวิธีนี้จะตรวจสอบ DOM เท่านั้น หากคุณใช้ Ajax หรือ AngularJS สิ่งนี้จะไม่ทำงานเนื่องจากจะมีการเรียกแบบอะซิงโครนัสที่เอกสารไม่สามารถตรวจพบได้
Homewrecker

3
นี่คือรหัส C # นี้ไม่ได้ทำงานกับ Java และคำถามที่ถามเกี่ยวกับJava
Kingamere

89

ใช้คลาสWebDriverWait

ดูที่นี่ด้วย

คุณสามารถคาดหวังให้แสดงองค์ประกอบบางอย่าง บางอย่างใน C #:

WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));

_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));

มันใช้งานได้ดีมาก มันเป็นวิธีที่ทันสมัยมากในการแก้ปัญหา
CrazyDart

3
@ EmmanuelAngelo.R TimeSpanเป็นโครงสร้างข้อมูล. Net
rjzii

12
ถ้าฉันไม่รู้ว่าองค์ประกอบใดจะอยู่ในหน้า
JustGoscha

3
วิธีนี้จะใช้ในการรอการโหลดองค์ประกอบเฉพาะและไม่ใช่ทั้งหน้า
xyz

1
สิ่งนี้ไม่รับประกันเลยว่าองค์ประกอบจะถูกโหลดเต็มไม่ตอบคำถาม ทุกคนสามารถอัปโหลดสิ่งนี้ได้อย่างไร
Boris D. Teoharov

36

หากคุณตั้งค่าการรอโดยนัยของไดรเวอร์ให้เรียกใช้findElementเมธอดบนองค์ประกอบที่คุณคาดว่าจะอยู่ในหน้าที่โหลด WebDriver จะสำรวจความคิดเห็นขององค์ประกอบนั้นจนกว่าจะพบองค์ประกอบหรือถึงค่าการหมดเวลา

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

แหล่งที่มา: implicit-waits


3
มันไม่ช่วยในการรอโหลดหน้า
xyz

หมายความว่าจะลองทำอะไรสักอย่างในช่วง 10 วินาทีก่อนที่มันจะยกข้อยกเว้น ดังนั้นจึงไม่สามารถแน่ใจได้ว่าจะใช้เวลาล่าช้า 10 วินาที
skysign

1
@xyz - ทำไมถึงไม่ช่วย?
MasterJoe2

@ testerjoe2 รอจนกว่าจะพบองค์ประกอบเฉพาะคำถามเกี่ยวกับวิธีรอโหลดหน้าเว็บ
xyz

35

โดยทั่วไปด้วย Selenium 2.0 เว็บไดรเวอร์ควรกลับการควบคุมไปยังรหัสการโทรเฉพาะเมื่อมีการกำหนดว่าหน้าโหลดแล้ว หากไม่เป็นเช่นนั้นคุณสามารถโทรหาwaitforelemementได้ซึ่งจะวนรอบการโทรfindelementจนกว่าจะพบหรือหมดเวลา (สามารถตั้งค่าการหมดเวลา)


2
กำลังเพิ่มคำตอบของ Paul กรุณาตรวจสอบยังนี้stackoverflow.com/questions/5858743/...
9ikhan

27
น่าเสียดายที่ Selenium 2 ไม่ได้รอให้โหลดหน้าเว็บในทุกกรณี ตัวอย่างเช่น WebElement: click () ไม่ต้องรอและสิ่งนี้จะถูกกล่าวอย่างชัดเจนใน Javadoc ที่เป็นของ อย่างไรก็ตามพวกเขาไม่ได้บอกวิธีที่ฉันสามารถตรวจสอบหน้าใหม่ที่จะโหลด If click() causes a new page to be loaded via an event or is done by sending a native event (which is a common case on Firefox, IE on Windows) then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
Sebi

จากdoc .. และเมธอดจะบล็อกจนกว่าการโหลดจะเสร็จสมบูรณ์ ...
xyz

2
@Karna: ใช่ในทางทฤษฎีมันควรและในทางปฏิบัติมันมักจะทำในเวลาส่วนใหญ่ การใช้ซีลีเนียมในเวลานั้นเน้นว่ามีบางครั้งที่คิดว่าหน้าเว็บโหลดเสร็จ แต่ก็ยังไม่เสร็จ ฉันไม่ได้ใช้ซีลีเนียมเมื่อเร็ว ๆ นี้ดังนั้นอาจเป็นเช่นนั้นหรืออาจจะยังไม่เป็นเช่นนั้น
พอลแฮ็ดฟีลด์

3
ฉันเห็นด้วย: โดยเฉพาะอย่างยิ่งไดรเวอร์ Internet explorer เป็นรถและกลับควบคุมทันทีในบางกรณีแม้ว่าหน้าจะยังคงโหลด ในกรณีของฉันฉันเพิ่มการรอโดยใช้JavascriptExecutorกำลังรอเอกสารอยู่แล้วสถานะเป็น "สมบูรณ์" เนื่องจากการเดินทางไปกลับจากซีลีเนียมไปยังเบราว์เซอร์สภาพการแข่งขันลดลงฉันเดาและนี่ "เสมอ" ใช้งานได้สำหรับฉัน หลังจาก "คลิก ()" เมื่อฉันคาดว่าหน้าจะโหลดฉันรออย่างชัดเจน (ใช้ WebDriverWait) สำหรับผู้อ่าน ]
dmansfield

22

การใช้ทับทิม:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}

17
Python ที่เทียบเท่า: WebDriverWait (คนขับ 10 คน). จนถึง (lambda d: d.execute_script ('return document.readyState') == 'เสร็จสิ้น')
blaze

2
Python ใช้โค้ดด้านบน แต่อย่าลืมบรรทัดนี้ .. | จาก selenium.webdriver.support.ui นำเข้า WebDriverWait
t3dodson

ฉันมีปัญหาในการคลิกที่องค์ประกอบเมื่อหน้าเว็บไม่ได้โหลดเต็ม ใน Python ฉันพยายาม time.sleep (30) มันได้ผล มันจะรอนานถึง 30 วินาทีสูงสุด ฉันลองใช้รหัสต่อไปนี้และมีประสิทธิภาพยิ่งขึ้นเร็วขึ้น WebDriverWait (ไดรเวอร์ 10). จนถึง (lambda d: driver.find_element_by_xpath ("// div [. = 'การบริหาร']"). คลิก ())
Riaz Ladhani

20

คุณอาจลบSystem.outบรรทัด มันถูกเพิ่มเพื่อวัตถุประสงค์ในการแก้ไขปัญหา

WebDriver driver_;

public void waitForPageLoad() {

    Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            System.out.println("Current Window State       : "
                + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
            return String
                .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                .equals("complete");
        }
    });
}

ขอบคุณสำหรับเคล็ดลับนี้ ฉันเพิ่มใน SeleniumHelper ของฉัน; cf เลย javabox
boly38

17

วิธีแก้ปัญหาทั้งหมดนี้ใช้ได้ในบางกรณี แต่ปัญหาเหล่านั้นอาจเกิดจากปัญหาอย่างน้อยหนึ่งในสองข้อ:

  1. พวกเขาไม่กว้างพอ - พวกเขาต้องการให้คุณรู้ล่วงหน้าว่าเงื่อนไขเฉพาะบางอย่างจะเป็นจริงของหน้าเว็บที่คุณกำลังจะไป (เช่นองค์ประกอบบางอย่างจะปรากฏขึ้น)

  2. พวกเขาจะเปิดให้เงื่อนไขการแข่งขันที่คุณใช้องค์ประกอบที่มีอยู่จริงในหน้าเก่าเช่นเดียวกับหน้าใหม่

นี่คือความพยายามของฉันในการแก้ปัญหาทั่วไปที่หลีกเลี่ยงปัญหานี้ (ใน Python):

ก่อนอื่นฟังก์ชั่นทั่วไป "รอ" (ใช้ WebDriverWait หากคุณต้องการฉันพบว่ามันน่าเกลียด):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

ถัดไปการแก้ปัญหาขึ้นอยู่กับข้อเท็จจริงที่ว่าซีลีเนียมบันทึกหมายเลข id (ภายใน) สำหรับองค์ประกอบทั้งหมดในหน้ารวมถึง<html>องค์ประกอบระดับบนสุด เมื่อหน้ารีเฟรชหรือโหลดมันจะได้รับองค์ประกอบ html ใหม่พร้อมรหัสใหม่

ดังนั้นสมมติว่าคุณต้องการคลิกลิงก์ที่มีข้อความ "ลิงค์ของฉัน" ตัวอย่างเช่น:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

สำหรับผู้ช่วยทั่วไปแบบ Pythonic ที่สามารถใช้ซ้ำได้และใช้ซ้ำได้คุณสามารถสร้างตัวจัดการบริบท:

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

และจากนั้นคุณสามารถใช้มันในการโต้ตอบซีลีเนียมใด ๆ :

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

ฉันคิดว่ามันเป็นกระสุน! คุณคิดอย่างไร?

ข้อมูลเพิ่มเติมในบล็อกโพสต์เกี่ยวกับที่นี่


ฉันอ่านหน้าเว็บของคุณก่อนค้นหาอีกครั้งโดยเฉพาะเจาะจงยิ่งขึ้นสำหรับรหัส java ซึ่งใช้โซลูชันของคุณ ไม่มีอะไรจนถึงตอนนี้ ...
แอนดรูว์ Lorien

11

นอกจากนี้คุณยังสามารถใช้คลาส: ExpectedConditionsเพื่อรอให้องค์ประกอบปรากฏในหน้าเว็บก่อนที่คุณจะสามารถดำเนินการใด ๆ เพิ่มเติมได้

คุณสามารถใช้ExpectedConditionsคลาสเพื่อพิจารณาว่าองค์ประกอบนั้นสามารถมองเห็นได้หรือไม่:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

ดูExpectedConditions class Javadocรายการเงื่อนไขทั้งหมดที่คุณสามารถตรวจสอบได้


11

คำตอบของ Imran rehashed สำหรับ Java 7:

    WebDriverWait wait = new WebDriverWait(driver, 30);

    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState"
            ).equals("complete");
        }
    });

10

นี่เป็นข้อ จำกัด ที่ร้ายแรงของ WebDriver เห็นได้ชัดว่าการรอองค์ประกอบจะไม่บ่งบอกถึงหน้าที่กำลังโหลดโดยเฉพาะอย่างยิ่ง DOM สามารถสร้างได้อย่างสมบูรณ์ (สถานะ onready) โดยที่ JS ยังคงดำเนินการอยู่และ CSS และรูปภาพยังคงโหลดอยู่

ฉันเชื่อว่าทางออกที่ง่ายที่สุดคือการตั้งค่าตัวแปร JS ตามเหตุการณ์ onload หลังจากทุกอย่างเริ่มต้นแล้วตรวจสอบและรอตัวแปร JS นี้ใน Selenium


มันง่ายหากเว็บไซต์ของคุณเป็นของคุณที่จะแก้ไข!
reinierpost

ใช่เพียงใช้ JavascriptExecutor เพื่อเรียกใช้ jQuery.js จากนั้นคุณสามารถเข้าถึง jQuery load events มันเป็นกรณีที่หายากเมื่อมีความจำเป็นแม้ว่า Webdriver มาตรฐานมีพลังมากพอที่จะทำ 98% ของการรอที่เหมาะสม
djangofan

@djangofan จะยอดเยี่ยมที่จะเห็นตัวอย่างของที่ ... ฉันเป็นคนที่แต่งตัวประหลาด Front-end ดังนั้นไม่แน่ใจว่า JavascriptExecutor ใช้ที่ไหนหรือวิธีการ
BradGreens

@BradGreens - ตกลงดูโครงการของฉันที่นี่: github.com/djangofan/jquery-growl-selenium-example github.com/djangofan/jquery-growl-selenium-exampleหากคุณมีแบนด์วิดท์ที่จะเสร็จสิ้นตัวอย่างนั้นฉันไม่สามารถทำให้ jGrowl ทำงานในโครงการทดสอบนั้นได้แม้ว่า jQuery จะทำงานได้ดี
djangofan

1
@BradGreens นอกเหนือจากความเห็นของ djangofan ดูคำตอบของฉันที่นี่: stackoverflow.com/a/24638792/730326
jmathew

9

หากคุณต้องการรอให้องค์ประกอบที่เฉพาะเจาะจงในการโหลดคุณสามารถใช้isDisplayed()วิธีการในRenderedWebElement:

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

(ตัวอย่างจากคู่มือการเริ่มต้น 5 นาที )


4
หนึ่งปีต่อมา (ซีลีเนียมรุ่นปัจจุบัน 2.23.1) ไม่มีRenderedWebElementใน API อย่างไรก็ตามวิธีการนี้สามารถใช้ได้โดยตรงบนisDisplayed() WebElement
Petr Janeček

1
การลงคะแนนเลือกตั้งแย่มากเมื่อสามารถหลีกเลี่ยงได้
reinierpost

8

รออย่างชัดเจนหรือรอตามเงื่อนไขในการรอนี้จนกว่าจะได้รับเงื่อนไขนี้

WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

สิ่งนี้จะรอทุกๆองค์ประกอบของเว็บเป็นเวลา 60 วินาที

ใช้การรอโดยปริยายสำหรับทุกองค์ประกอบในหน้าจนกว่าจะถึงเวลาที่กำหนด

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

สิ่งนี้จะรอทุกๆองค์ประกอบของเว็บเป็นเวลา 60 วินาที


5

ใช้การรอโดยปริยายสำหรับทุกองค์ประกอบในหน้าจนกว่าจะถึงเวลาที่กำหนด

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

การรอนี้สำหรับทุกองค์ประกอบในหน้าเป็นเวลา 30 วินาที

การรออื่นคือการรออย่างชัดแจ้งหรือการรอตามเงื่อนไขในการรอนี้จนกว่าจะได้รับเงื่อนไข

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

ใน id ให้องค์ประกอบองค์ประกอบคงที่ซึ่งจะปรากฏบนหน้าเว็บทันทีที่โหลดหน้า


4

ฉันประหลาดใจที่เพรดิเคตไม่ใช่ตัวเลือกแรกเนื่องจากคุณมักจะรู้ว่าองค์ประกอบใดที่คุณจะโต้ตอบในหน้าถัดไปที่คุณรอโหลด แนวทางของฉันคือการสร้างเพรดิเคต / ฟังก์ชั่นเช่นwaitForElementByID(String id)และwaitForElemetVisibleByClass(String className)อื่น ๆ จากนั้นใช้และนำกลับมาใช้ใหม่ได้ทุกที่ที่ต้องการไม่ว่าจะเป็นการโหลดหน้าหรือเปลี่ยนเนื้อหาของหน้า

ตัวอย่างเช่น,

ในชั้นทดสอบของฉัน:

driverWait.until(textIsPresent("expectedText");

ในระดับผู้ปกครองของฉันทดสอบ:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

แม้ว่าสิ่งนี้จะดูเหมือนมาก แต่ก็ดูแลการตรวจสอบซ้ำ ๆ สำหรับคุณและช่วงเวลาในการตรวจสอบความถี่ที่สามารถตั้งค่าได้พร้อมกับเวลารอคอยขั้นสุดท้ายก่อนที่จะหมดเวลา นอกจากนี้คุณจะใช้วิธีการดังกล่าวอีกครั้ง

ในตัวอย่างนี้ผู้ปกครองชั้นเรียนที่กำหนดไว้และริเริ่มและWebDriver driverWebDriverWait driverWait

ฉันหวังว่านี่จะช่วยได้.


นี่ช่วยฉันได้! ขอบคุณสำหรับตัวอย่างที่ยอดเยี่ยมนี้ ฉันเพิ่มใน SeleniumHelper ของฉัน; cf เลย javabox
boly38

4

วิธีที่ดีที่สุดในการรอให้โหลดหน้าเว็บเมื่อใช้การเชื่อม Java สำหรับ WebDriver คือการใช้รูปแบบการออกแบบ Page Object กับ PageFactory สิ่งนี้ช่วยให้คุณใช้ประโยชน์จากสิ่งAjaxElementLocatorFactoryที่ทำให้มันเป็นเพียงการรอคอยระดับโลกสำหรับองค์ประกอบทั้งหมดของคุณ มันมีข้อ จำกัด เกี่ยวกับองค์ประกอบต่าง ๆ เช่นดรอปบ็อกซ์หรือการเปลี่ยนจาวาสคริปต์ที่ซับซ้อน แต่มันจะลดจำนวนโค้ดที่จำเป็นลงอย่างมากและเพิ่มความเร็วในการทดสอบ ตัวอย่างที่ดีสามารถพบได้ในบล็อกนี้ ทำความเข้าใจพื้นฐานของ Core Java

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html


4

โซลูชัน NodeJS:

ในNodejsคุณสามารถรับมันผ่านทางสัญญา ...

หากคุณเขียนรหัสนี้คุณสามารถมั่นใจได้ว่าหน้าเว็บจะโหลดเต็มเมื่อคุณไปที่ ...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

หากคุณเขียนรหัสนี้คุณจะนำทางและซีลีเนียมจะรอ 3 วินาที ...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

จากเอกสารซีลีเนียม:

this.get (url) →หลังจากนั้น

กำหนดเวลาคำสั่งเพื่อนำทางไปยัง URL ที่กำหนด

ผลตอบแทนที่ได้สัญญาที่จะได้รับการแก้ไขเมื่อเอกสารมีการโหลดเสร็จแล้ว

เอกสารซีลีเนียม (โหนด)


4

นี่เป็นเวอร์ชั่น Java 8 ของคำตอบที่ถูกโหวตมากที่สุดในปัจจุบัน:

WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));

ในกรณีที่myDriverเป็นWebDriverวัตถุ (ประกาศก่อนหน้า)

หมายเหตุ : โปรดทราบว่าวิธีนี้ ( document.readyState) ตรวจสอบ DOM เท่านั้น


4

โทรด้านล่างฟังก์ชั่นในสคริปต์ของคุณนี้จะรอจนกว่าหน้าจะไม่โหลดโดยใช้จาวาสคริปต์

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}

ฉันเปลี่ยนบูลีนเป็นโมฆะ แต่ไม่ได้ทำงานใน Chrome
nosequeweaponer

3
/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

คุณสามารถเปลี่ยนจากเอกสารเป็นองค์ประกอบในกรณีที่มีการเปลี่ยนแปลงเฉพาะบางส่วนของเอกสาร

เทคนิคนี้ได้รับแรงบันดาลใจจากคำตอบของตั้งแต่พื้นฐาน


3

SeleniumWaiter :

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

และคุณใช้มัน :

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}

3

คุณสามารถใช้วิธีที่มีอยู่ด้านล่างเพื่อตั้งเวลาสำหรับ pageeLoadTimeout ในตัวอย่างด้านล่างหากหน้านั้นใช้เวลาในการโหลดมากกว่า 20 วินาทีจากนั้นมันจะส่งข้อยกเว้นการโหลดหน้าซ้ำ

 WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)

2

คุณสามารถรอให้องค์ประกอบปรากฏบนหน้าเว็บก่อนที่คุณจะสามารถดำเนินการใด ๆ (เช่นองค์ประกอบ. คลิก ())

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
  .until(new ExpectedCondition<WebElement>(){
        @Override
        public WebElement apply(WebDriver d) {
        return d.findElement(By.id("myDynamicElement"));
}});

นี่คือสิ่งที่ฉันใช้สำหรับสถานการณ์ที่คล้ายกันและทำงานได้ดี


ฉันคิดว่ารอ driver.get สำหรับฟังก์ชัน onload ให้เสร็จก่อนที่จะกลับไปที่การควบคุมรหัสเว้นแต่หน้ามีจำนวนมากของอาแจ็กซ์
โก๊ะ

2

วิธีง่ายๆของฉัน:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }

2

วิธีที่ดีที่สุดที่ฉันเคยเห็นคือใช้stalenessOfExpectedCondition เพื่อรอหน้าเก่าให้เก่า

ตัวอย่าง:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

มันจะรอสิบวินาทีเพื่อให้แท็ก HTML เก่ากลายเป็นค้างแล้วจากนั้นก็ยกเว้นหากไม่เกิดขึ้น


1
WebElement ที่กำลังค้างไม่ได้หมายความว่าหน้าใหม่กำลังโหลดเสร็จแล้ว
Corey Goldberg

แน่นอน แต่หมายความว่าหน้าเก่าเสร็จสิ้นการขนถ่าย จากประสบการณ์ของฉันมันเป็นเรื่องสำคัญที่จะต้องรู้เมื่อหน้าเก่าไม่ได้โหลดหรือถ้ามันหยุดลงด้วยเหตุผลบางอย่าง
forresthopkinsa

แน่นอนฉันมักจะใช้ stalenessOf ร่วมกับการทดสอบอื่น ๆ เพื่อให้ได้กระบวนการขนถ่าย / โหลดเต็ม
forresthopkinsa

2

ฉันใช้ node + selenium-webdriver (เวอร์ชันใดเป็น 3.5.0 ตอนนี้) สิ่งที่ฉันทำเพื่อสิ่งนี้คือ:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))

2

คุณสามารถใช้รอ โดยทั่วไปจะมีซีลีเนียมรออยู่ 2 ชนิด

  • รอโดยปริยาย
  • รออย่างชัดเจน

- การรอโดยนัย

ง่ายมากโปรดดูไวยากรณ์ด้านล่าง:

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

- รออย่างชัดเจน

รออย่างชัดเจนหรือรอตามเงื่อนไขในการรอนี้จนกว่าจะเกิดเงื่อนไขที่กำหนด

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

คุณสามารถใช้คุณสมบัติอื่น ๆ เช่นvisblityOf(),visblityOfElement()



2

ในกรณีของฉันฉันใช้สิ่งต่อไปนี้เพื่อทราบสถานะการโหลดหน้า ในแอปพลิเคชันของเรากำลังโหลด gif (s) และฉันฟังพวกเขาดังต่อไปนี้เพื่อกำจัดเวลารอที่ไม่พึงประสงค์ในสคริปต์

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

ตำแหน่งที่ xpath หา gif ใน HTML DOM หลังจากนี้คุณอาจใช้วิธีการกระทำของคุณคลิก

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }

2

คำตอบทั้งหมดเหล่านี้ต้องใช้รหัสมากเกินไป นี่ควรเป็นสิ่งที่เรียบง่ายเหมือนกัน

ทำไมไม่เพียงแค่ฉีดจาวาสคริปต์ง่ายๆด้วย webdriver และตรวจสอบ นี่คือวิธีที่ฉันใช้ในชั้นเรียนของฉัน จาวาสคริปต์นั้นค่อนข้างธรรมดาแม้ว่าคุณจะไม่รู้จัก js

    def js_get_page_state(self):        
    """
    Javascript for getting document.readyState
    :return: Pages state.

    More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
    """
    ready_state = self.driver.execute_script('return document.readyState')
    if ready_state == 'loading':
        self.logger.info("Loading Page...")
    elif ready_state == 'interactive':
        self.logger.info("Page is interactive")
    elif ready_state == 'complete':
        self.logger.info("The page is fully loaded!")
    return ready_state

1

วิธีให้ซีลีเนียมรอให้โหลดหน้าเว็บหลังจากคลิกให้วิธีที่น่าสนใจดังต่อไปนี้:

  1. เก็บการอ้างอิงถึง WebElementจากหน้าเก่า
  2. คลิกที่ลิงค์
  3. ดำเนินการเรียกใช้งานต่อWebElementไปจนกว่าStaleElementReferenceExceptionจะถูกโยนทิ้ง

รหัสตัวอย่าง:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});

ความคิดที่ดี! ฉันไม่เคยคิดที่จะจัดการกับสถานการณ์นี้โดยการตรวจสอบตรงกันข้ามกับการโหลดหน้าเว็บที่ประสบความสำเร็จหน้าเว็บที่ประสบความสำเร็จในการยกเลิกการโหลด แม้ว่าจะเป็นตัวเลือกที่ดีที่สุดหรือไม่นั้นขึ้นอยู่กับว่า StaleElementReferenceException ใช้เวลาน้อยลงหรือไม่มากกว่าการรอให้โหลดสำเร็จ อย่างไรก็ตามอีกวิธีที่ดีที่จะทำ
โจเซฟออร์แลนโด

4
สิ่งนี้จะไม่บอกคุณว่าหน้าปัจจุบันถูกโหลดหรือไม่มันจะบอกคุณว่าหน้าสุดท้าย (เฉพาะองค์ประกอบหนึ่ง) ถูกยกเลิกการโหลดหรือไม่ คุณยังจะต้องรอให้หน้าปัจจุบันโหลด BTW new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element))คุณสามารถแทนที่รหัสของคุณข้างต้นด้วย
JeffC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.