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


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.