답변:
다음 코드를 사용하여 페이지로드를 확인할 수도 있습니다.
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"));
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"));
드라이버의 암시 적 대기를 설정 한 다음 findElement
로드 된 페이지에있을 것으로 예상되는 요소 에서 메소드 를 호출 하면 WebDriver는 요소를 찾거나 시간 종료 값에 도달 할 때까지 해당 요소를 폴링합니다.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
출처 : 암시 적 대기
일반적으로 Selenium 2.0의 경우 웹 드라이버는 페이지가로드 된 것으로 판단되면 호출 코드로 제어를 반환해야합니다. 그렇지 않은 waitforelemement
경우을 호출 할 수 있습니다. 호출 findelement
은 발견되거나 시간 초과 될 때까지 라운드 호출을 순환 합니다 (시간 초과를 설정할 수 있음).
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.
JavascriptExecutor
document.readyState가 "완료"되기를 기다리는을 사용하여 대기를 추가했습니다 . 셀레늄에서 브라우저로의 왕복으로 인해 경쟁 조건이 완화되고이 "항상"작동합니다. 페이지가로드 될 것으로 예상되는 "click ()"후에는 준비 상태를 명시 적으로 (WebDriverWait 사용) 기다립니다. ]
루비 구현 :
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
@driver.execute_script("return document.readyState;") == "complete"
}
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");
}
});
}
이러한 모든 솔루션은 특정 경우에 적합하지만 두 가지 가능한 문제 중 하나 이상이 발생합니다.
그것들은 충분히 일반적이지 않습니다-그들은 당신이 당신이 가고있는 페이지에 대해 특정 조건이 참임을 미리 알고 싶어합니다 (예 : 일부 요소가 표시됩니다)
이전 페이지와 새 페이지에 실제로 존재하는 요소를 사용하는 경쟁 조건에 개방적입니다.
파이썬 에서이 문제를 피하는 일반적인 솔루션에 대한 나의 시도는 다음과 같습니다.
먼저, 일반적인 "대기"함수 (원하는 경우 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__))
다음으로 솔루션은 셀레늄이 최상위 <html>
요소를 포함하여 페이지의 모든 요소에 대해 (내부) id 번호를 기록한다는 사실에 의존합니다 . 페이지를 새로 고치거나로드하면 새 ID를 가진 새로운 html 요소가 표시됩니다.
예를 들어, "my link"라는 텍스트가있는 링크를 클릭한다고 가정하면 다음과 같습니다.
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)
더 파이썬적이고 재사용 가능한 일반 도우미를 위해 컨텍스트 관리자를 만들 수 있습니다.
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()
방탄이라고 생각합니다! 어떻게 생각해?
블로그 게시물에 대한 자세한 정보는 여기
클래스 : ExpectedConditions
를 사용하여 웹 페이지에 요소가 표시 될 때까지 명시 적으로 기다렸다가 추가 조치를 취할 수 있습니다.
ExpectedConditions
클래스를 사용하여 요소가 표시되는지 확인할 수 있습니다.
WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));
ExpectedConditions class Javadoc
확인할 수있는 모든 조건 목록을 참조 하십시오.
이것은 WebDriver의 심각한 한계 인 것 같습니다. 분명히 요소를 기다리는 것은 페이지가로드되는 것을 의미하지는 않습니다. 특히 DOM이 완전히 빌드되고 (준비 상태) JS가 여전히 실행 중이고 CSS 및 이미지가 여전히로드 될 수 있습니다.
가장 간단한 해결책은 모든 것이 초기화 된 후 onload 이벤트에 JS 변수를 설정하고 Selenium 에서이 JS 변수를 확인하고 기다리는 것입니다.
특정 요소가로드되기를 기다리려면 다음에서 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 분 시작 안내서의 예 )
RenderedWebElement
에는 API 가 없습니다 . 그러나 isDisplayed()
이제 방법은에서 직접 사용할 수 있습니다 WebElement
.
이 조건이 주어질 때까지이 대기에서 명시 적으로 대기 또는 조건부 대기.
WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));
모든 웹 요소를 60 초 동안 기다립니다.
주어진 시간까지 페이지의 모든 요소를 암시 적으로 기다리십시오.
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
모든 웹 요소를 60 초 동안 기다립니다.
주어진 시간까지 페이지의 모든 요소를 암시 적으로 기다리십시오.
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
30 초 동안 페이지의 모든 요소를 기다립니다.
다른 대기는 지정된 대기 시간까지이 대기에서 명시 적으로 대기 또는 조건부 대기입니다.
WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
id에서 페이지가로드 되 자마자 페이지에 표시되는 정적 요소 ID를 제공하십시오.
로드 할 페이지에서 다음에 상호 작용할 요소를 일반적으로 알고 있으므로 술어가 첫 번째 선택이 아니라는 것에 놀랐습니다. 내 접근 방식은 항상 waitForElementByID(String id)
and 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 driver
했습니다 WebDriverWait driverWait
.
이게 도움이 되길 바란다.
WebDriver에 Java 바인딩을 사용할 때 페이지로드를 기다리는 가장 좋은 방법은 PageFactory와 함께 페이지 오브젝트 디자인 패턴을 사용하는 것입니다. 이를 통해 AjaxElementLocatorFactory
어느 요소 를 사용하든 간단히 모든 요소를 전역 적으로 기다리는 역할을합니다. 드롭 박스 또는 복잡한 자바 스크립트 전환과 같은 요소에는 제한이 있지만 필요한 코드의 양을 크게 줄이고 테스트 시간을 단축합니다. 이 블로그 포스트에서 좋은 예를 찾을 수 있습니다. 핵심 Java에 대한 기본 이해가 가정됩니다.
http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html
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...
Selenium 문서에서 :
this.get (url) → Thenable
주어진 URL로 이동하도록 명령을 예약합니다.
문서의 로드 가 완료 되면 해결 될 가능성을 리턴합니다 .
다음은 현재 가장 많이 답변 된 답변 의 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 만 검사합니다.
자바 스크립트를 사용하여 페이지가로드되지 않을 때까지 기다립니다.
public static boolean isloadComplete(WebDriver driver)
{
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
|| ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
/**
* 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;
}
});
}
문서의 일부만 변경되는 경우 문서에서 요소로 변경할 수 있습니다.
이 기술은 sincebasic의 답변에서 영감을 받았습니다.
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
}
element.click ()과 같은 작업을 수행하기 전에 웹 페이지에 요소가 표시 될 때까지 명시 적으로 기다릴 수 있습니다.
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"));
}});
이것은 비슷한 시나리오에 사용 된 것으로 잘 작동합니다.
내가 본 가장 좋은 방법은 stalenessOf
ExpectedCondition 을 사용 하여 이전 페이지가 오래 될 때까지 기다리는 것입니다.
예:
WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));
기존 HTML 태그가 오래 될 때까지 10 초 동안 기다렸다가 발생하지 않으면 예외가 발생합니다.
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';
}))
대기를 사용할 수 있습니다. 기본적으로 셀레늄에는 두 가지 유형의 대기가 있습니다.
-암시 적 대기
이것은 매우 간단합니다. 아래 구문을 참조하십시오.
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
-명시 적 대기
주어진 조건이 발생할 때까지이 대기에서 명시 적으로 대기 또는 조건부 대기입니다.
WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
와 같은 다른 속성을 사용할 수 있습니다 visblityOf()
.visblityOfElement()
누군가 셀레 니드를 사용하는 경우 :
public static final Long SHORT_WAIT = 5000L; // 5 seconds
$("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);
더 많은 조건은 여기에서 찾을 수 있습니다 : http://selenide.org/javadoc/3.0/com/codeborne/selenide/Condition.html
내 경우에는 다음을 사용하여 페이지로드 상태를 알았습니다. 우리의 응용 프로그램에서 gif 가로 드되고 스크립트에서 원치 않는 대기 시간을 제거하기 위해 다음과 같이 듣습니다.
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가 HTML DOM에서 gif를 찾는 위치. 이 후, 당신은 또한 당신의 행동 방법 클릭을 구현할 수 있습니다.
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();
}
이 모든 답변에는 너무 많은 코드가 필요합니다. 이것은 일반적인 것으로 간단한 것이어야합니다.
왜 웹 드라이버로 간단한 자바 스크립트를 주입하고 확인하지 않습니까? 이것은 내 웹 스크래퍼 클래스에서 사용하는 방법입니다. 자바 스크립트는 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
클릭 후 Selenium이 페이지로드를 기다리도록하는 방법 은 다음과 같은 흥미로운 접근 방식을 제공합니다.
WebElement
이전 페이지 의에 대한 참조를 저장 하십시오.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;
}
});
new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element))
.