Selenium Web Driver:JavaScript가 있는 복잡한 페이지가 로드될 때까지 기다립니다.
셀레늄자바스크립트
이 JavaScript 코드는 잘 작성되지 않았지만 아무것도 변경할 수 없습니다. 요소가 .findElement()
방법
를 대기하는 , 방법은 가능한 해결 방법은 다음과 같습니다.
- 하여 WebDriver의 JavaScript 합니다.
document.body.innerHTML
변수 " " "에서body
. body
" " " " the to to 。body
합니다.이것들이같은경우인크리먼트카운터를설정합니다.notChangedCount
않으면 을 설정하다notChangedCount
0으로로로합합합합합- 리트 타임(예를 들어 50밀리초)을 기다립니다.
- 가 일정 들어 ) 되지 않은 , "500밀리초"(예를 들어 "500밀리초")로 표시됩니다.
notChangedCount >= 10
츠키다그렇지 않으면 첫 번째 스텝으로 루프합니다.
당신은 그것이 유효한 해결책이라고 생각합니까?
만약 누군가가 실제로 일반적이고 항상 적용 가능한 답을 알았다면, 그것은 오래 전에 어디에서나 시행되었을 것이고 우리의 삶을 훨씬 더 쉽게 만들었을 것이다.
할 수 있는 일은 많지만, 그 하나하나에 문제가 있습니다.
말했듯이 잘 그 할 수 Ashwin Prabhu에서 그 할 수 .
window
★★★★★★★★★★★★★★★★★」document
etc. 이 할 수 .etc . etc 、 솔 etc 、 etc etc of of of of of of of of of of of of of of of of of of of of of of of of of of etc,,, etc etc etc etc etc etc etc etc etc 。HTML 코드를 관찰하여 수정 여부를 확인하는 것은 나쁘지 않습니다(또한 원본 HTML과 편집되지 않은 HTML을 직접 얻을 수 있는 방법도 있습니다).
WebDriver
단:). §,- 실제로 페이지를 단언하는 데 시간이 오래 걸리고 테스트가 상당히 길어질 수 있습니다.
- 당신은 올바른 간격이 무엇인지 결코 모른다.스크립트가 500밀리초 이상 걸리는 대용량 파일을 다운로드하고 있을 수 있습니다.당사의 사내 페이지에는 IE에서 몇 초 걸리는 스크립트가 몇 개 있습니다.컴퓨터 리소스가 일시적으로 부족할 수 있습니다.예를 들어 바이러스 대책으로 CPU가 완전히 동작한다고 가정하면 복잡한 스크립트가 아닌 경우에도 500밀리초의 시간이 너무 짧을 수 있습니다.
- 실행하지 않는 스크립트가 있습니다.(지연이라고 부른다.
setTimeout()
를 반복하여 작업하고 실행 시마다 HTML을 변경할 수 있습니다.Web 2.0 web web web web 。택택오스가장 일반적으로 사용되는 메서드를 덮어쓰고 이를 사용하는 스크립트는 완료된 것으로 간주할 수 있지만...확실하진 않겠죠 - 하는 것 것을 ? 은 단순히 을 바꾸는 것이 수천 할 수 . 그것은 단지 몇 가지뿐 아니라 수천 가지 일을 할 수 있다.
innerHTML
도움이 될 만한 도구가 있습니다.즉, 프로그레스 리스너와 ns의 조합IWeb Progress Listener 등단, 이에 대한 브라우저 지원은 형편없습니다.파이어폭스는 FF4 이후(아직도 진화하고 있음)부터 지원을 시도하기 시작했으며 IE는 IE9에서 기본 지원을 하고 있습니다.
조만간 또 다른 결점이 있는 해결책을 생각해 낼 수 있을 것 같아요.사실, "이제 페이지가 완성되었습니다"라고 말해야 할 시기에 대한 명확한 답변은 없습니다.왜냐하면 이 스크립트는 계속 기능하기 때문입니다.당신에게 가장 도움이 되는 것을 고르되, 그것의 단점을 조심하라.
고마워요 애쉬윈!
내 경우 일부 요소에서 jquery 플러그인이 실행될 때까지 기다려야 합니다.구체적으로는 "qtip"
당신의 힌트를 바탕으로, 그것은 나에게 완벽하게 작용했습니다.
wait.until( new Predicate<WebDriver>() {
public boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
}
);
메모: 웹 드라이버 2를 사용하고 있습니다.
Javascript 의 jQuery 。 후 Javascript 실행 여부 jQuery.active
0
★★★★★★★★★★★★★★★★★」document.readyState
complete
JS jQuery는 jQuery를 사용합니다.
public boolean waitForJStoLoad() {
WebDriverWait wait = new WebDriverWait(driver, 30);
// wait for jQuery to load
ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
try {
return ((Long)executeJavaScript("return jQuery.active") == 0);
}
catch (Exception e) {
return true;
}
}
};
// wait for Javascript to load
ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
return executeJavaScript("return document.readyState")
.toString().equals("complete");
}
};
return wait.until(jQueryLoad) && wait.until(jsLoad);
}
페이지상의 html이 안정될 때까지 기다렸다가 요소와 대화할 경우 정기적으로 DOM을 폴링하고 결과를 비교할 수 있습니다.폴링 시간 내에 DOM이 같으면 금입니다.예를 들어 최대 대기시간과 페이지 폴링 사이의 시간을 지난 후 비교합니다.심플하고 효과적입니다.
public void waitForJavascript(int maxWaitMillis, int pollDelimiter) {
double startTime = System.currentTimeMillis();
while (System.currentTimeMillis() < startTime + maxWaitMillis) {
String prevState = webDriver.getPageSource();
Thread.sleep(pollDelimiter); // <-- would need to wrap in a try catch
if (prevState.equals(webDriver.getPageSource())) {
return;
}
}
}
JS 라이브러리는 창에서 잘 알려진 변수를 정의/초기화합니까?
이 경우 변수가 나타날 때까지 기다릴 수 있습니다.사용할 수 있습니다.
((JavascriptExecutor)driver).executeScript(String script, Object... args)
이 상태를 테스트합니다(예:window.SomeClass && window.SomeClass.variable != null
''을 true
false
.
이것을 에 싸서 스크립트가 반환될 때까지 기다립니다.true
.
저도 같은 문제가 있었어요.이 솔루션은 WebDriverDoku에서 사용할 수 있습니다.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp
다음 코드는 내 경우 완벽하게 작동합니다. 내 페이지에는 복잡한 자바 스크립트가 포함되어 있습니다.
public void checkPageIsReady() {
JavascriptExecutor js = (JavascriptExecutor)driver;
//Initially bellow given if condition will check ready state of page.
if (js.executeScript("return document.readyState").toString().equals("complete")){
System.out.println("Page Is loaded.");
return;
}
//This loop will rotate for 25 times to check If page Is ready after every 1 second.
//You can replace your value with 25 If you wants to Increase or decrease wait time.
for (int i=0; i<25; i++){
try {
Thread.sleep(1000);
}catch (InterruptedException e) {}
//To check page ready state.
if (js.executeScript("return document.readyState").toString().equals("complete")){
break;
}
}
}
출처 - Selenium WebDriver에서 페이지 로드/준비 대기 방법
페이지의 요소를 찾기 전에 페이지가 로드되었는지 확인하려면 다음 두 가지 조건을 사용할 수 있습니다.
WebDriverWait wait = new WebDriverWait(driver, 50);
아래 readyState를 사용하면 페이지가 로드될 때까지 대기합니다.
wait.until((ExpectedCondition<Boolean>) wd ->
((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
아래 JQuery는 데이터가 로드되지 않을 때까지 기다립니다.
int count =0;
if((Boolean) executor.executeScript("return window.jQuery != undefined")){
while(!(Boolean) executor.executeScript("return jQuery.active == 0")){
Thread.sleep(4000);
if(count>4)
break;
count++;
}
}
이 JavaScript Code 후에 webElement를 찾습니다.
WebElement we = wait.until(ExpectedConditions.presenceOfElementLocated(by));
저는 개발자들에게 ("ae" 오브젝트에) 접근할 수 있는 JavaScript 변수 "isProcessing"을 만들도록 요청했습니다.이 변수 "isProcessing"은 실행 시작 시 설정되며 완료 시 클리어됩니다.그런 다음 100밀리초마다 5회 연속 전송될 때까지 변경 없이 총 500밀리초 동안 이를 체크하는 어큐뮬레이터에서 실행합니다.30초가 지나면 그때까지 무슨 일이 일어났어야 했기 때문에 예외를 두겠습니다.이건 C#이에요.
public static void WaitForDocumentReady(this IWebDriver driver)
{
Console.WriteLine("Waiting for five instances of document.readyState returning 'complete' at 100ms intervals.");
IJavaScriptExecutor jse = (IJavaScriptExecutor)driver;
int i = 0; // Count of (document.readyState === complete) && (ae.isProcessing === false)
int j = 0; // Count of iterations in the while() loop.
int k = 0; // Count of times i was reset to 0.
bool readyState = false;
while (i < 5)
{
System.Threading.Thread.Sleep(100);
readyState = (bool)jse.ExecuteScript("return ((document.readyState === 'complete') && (ae.isProcessing === false))");
if (readyState) { i++; }
else
{
i = 0;
k++;
}
j++;
if (j > 300) { throw new TimeoutException("Timeout waiting for document.readyState to be complete."); }
}
j *= 100;
Console.WriteLine("Waited " + j.ToString() + " milliseconds. There were " + k + " resets.");
}
제대로 하려면 예외를 처리해야 합니다.
iFrame을 기다리는 방법은 다음과 같습니다.이를 위해서는 JUnit 테스트클래스가 RemoteWebDriver 인스턴스를 페이지 객체에 전달해야 합니다.
public class IFrame1 extends LoadableComponent<IFrame1> {
private RemoteWebDriver driver;
@FindBy(id = "iFrame1TextFieldTestInputControlID" )
public WebElement iFrame1TextFieldInput;
@FindBy(id = "iFrame1TextFieldTestProcessButtonID" )
public WebElement copyButton;
public IFrame1( RemoteWebDriver drv ) {
super();
this.driver = drv;
this.driver.switchTo().defaultContent();
waitTimer(1, 1000);
this.driver.switchTo().frame("BodyFrame1");
LOGGER.info("IFrame1 constructor...");
}
@Override
protected void isLoaded() throws Error {
LOGGER.info("IFrame1.isLoaded()...");
PageFactory.initElements( driver, this );
try {
assertTrue( "Page visible title is not yet available.", driver
.findElementByCssSelector("body form#webDriverUnitiFrame1TestFormID h1")
.getText().equals("iFrame1 Test") );
} catch ( NoSuchElementException e) {
LOGGER.info("No such element." );
assertTrue("No such element.", false);
}
}
@Override
protected void load() {
LOGGER.info("IFrame1.load()...");
Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring( NoSuchElementException.class )
.ignoring( StaleElementReferenceException.class ) ;
wait.until( ExpectedConditions.presenceOfElementLocated(
By.cssSelector("body form#webDriverUnitiFrame1TestFormID h1") ) );
}
....
님의 nodejs
셀레늄 도서관, 나는 다음과 같은 단편들을 사용했다.되는 두 의 오브젝트를 , 이에서는 두 개의 오브젝트를 찾고 .이 예에서는 다음과 같습니다.<SOME PROPERTY>
,10000
는 밀리초입니다.<NEXT STEP HERE>
창에서 속성을 찾은 후 발생하는 현상입니다.
driver.wait( driver => {
return driver.executeScript( 'if(window.hasOwnProperty(<SOME PROPERTY>) && window.hasOwnProperty(<SOME PROPERTY>)) return true;' ); }, 10000).then( ()=>{
<NEXT STEP HERE>
}).catch(err => {
console.log("looking for window properties", err);
});
이것은 동적으로 렌더링된 웹 사이트에서 잘 작동합니다.
- 전체 페이지가 로드될 때까지 기다립니다.
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
- 항상 실패하는 더미 조건을 사용하여 암묵적으로 대기합니다.
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true
}
catch (TimeoutException te) {
}
- 마지막으로 html 소스를 얻는 대신 첫 번째 html 태그의 outerhtml을 꺼냅니다.
String script = "return document.getElementsByTagName(\"html\")[0].outerHTML;";
content = ((JavascriptExecutor) driver).executeScript(script).toString();
이 문제를 처리하기 위해 몇 가지 논리를 작성할 수 있습니다.을 써 .WebElement
이 방법을 세번, 시간을 '3번'에 할 수 .무효로 하다WebElement
.
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://www.crowdanalytix.com/#home");
WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
int i = 1;
while (webElement == null && i < 4) {
webElement = getWebElement(driver, "homessssssssssss");
System.out.println("calling");
i++;
}
System.out.println(webElement.getTagName());
System.out.println("End");
driver.close();
}
public static WebElement getWebElement(WebDriver driver, String id) {
WebElement myDynamicElement = null;
try {
myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By
.id(id)));
return myDynamicElement;
} catch (TimeoutException ex) {
return null;
}
}
제코드로.
Window.set Timeout window window window 。
따라서 브라우저에 액티비티가 없는 경우 함수를 재귀적으로 호출(42회)하는 데 100ms가 소요되며 브라우저가 다른 작업을 수행 중이면 더 많은 시간이 소요됩니다.
ExpectedCondition<Boolean> javascriptDone = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
try{//window.setTimeout executes only when browser is idle,
//introduces needed wait time when javascript is running in browser
return ((Boolean) ((JavascriptExecutor) d).executeAsyncScript(
" var callback =arguments[arguments.length - 1]; " +
" var count=42; " +
" setTimeout( collect, 0);" +
" function collect() { " +
" if(count-->0) { "+
" setTimeout( collect, 0); " +
" } "+
" else {callback(" +
" true" +
" );}"+
" } "
));
}catch (Exception e) {
return Boolean.FALSE;
}
}
};
WebDriverWait w = new WebDriverWait(driver,timeOut);
w.until(javascriptDone);
w=null;
는 document 콜 이 실행되고 있는 콜에 하는 경우에만)로 수 .
" function collect() { " +
" if(!((typeof jQuery === 'undefined') || ((jQuery.active === 0) && ($(\":animated\").length === 0))) && (document.readyState === 'complete')){" +
" count=42;" +
" setTimeout( collect, 0); " +
" }" +
" else if(count-->0) { "+
" setTimeout( collect, 0); " +
" } "+
...
편집: 새 페이지가 로드되어 테스트가 무기한 응답을 멈출 수 있는 경우 executeAsyncScript가 제대로 작동하지 않는 것을 알 수 있습니다.대신 이 스크립트를 사용하는 것이 좋습니다.
public static ExpectedCondition<Boolean> documentNotActive(final int counter){
return new ExpectedCondition<Boolean>() {
boolean resetCount=true;
@Override
public Boolean apply(WebDriver d) {
if(resetCount){
((JavascriptExecutor) d).executeScript(
" window.mssCount="+counter+";\r\n" +
" window.mssJSDelay=function mssJSDelay(){\r\n" +
" if((typeof jQuery != 'undefined') && (jQuery.active !== 0 || $(\":animated\").length !== 0))\r\n" +
" window.mssCount="+counter+";\r\n" +
" window.mssCount-->0 &&\r\n" +
" setTimeout(window.mssJSDelay,window.mssCount+1);\r\n" +
" }\r\n" +
" window.mssJSDelay();");
resetCount=false;
}
boolean ready=false;
try{
ready=-1==((Long) ((JavascriptExecutor) d).executeScript(
"if(typeof window.mssJSDelay!=\"function\"){\r\n" +
" window.mssCount="+counter+";\r\n" +
" window.mssJSDelay=function mssJSDelay(){\r\n" +
" if((typeof jQuery != 'undefined') && (jQuery.active !== 0 || $(\":animated\").length !== 0))\r\n" +
" window.mssCount="+counter+";\r\n" +
" window.mssCount-->0 &&\r\n" +
" setTimeout(window.mssJSDelay,window.mssCount+1);\r\n" +
" }\r\n" +
" window.mssJSDelay();\r\n" +
"}\r\n" +
"return window.mssCount;"));
}
catch (NoSuchWindowException a){
a.printStackTrace();
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
return ready;
}
@Override
public String toString() {
return String.format("Timeout waiting for documentNotActive script");
}
};
}
HTML이 안정될 때까지 폴링하겠다는 당신의 생각이 마음에 들어요.나는 내 해결책에 그것을 추가할 수 있다.다음 접근법은 C#에 있으며 jQuery가 필요합니다.
저는 Success Factors(SaaS) 테스트 프로젝트의 개발자입니다.이 테스트 프로젝트에서는 개발자 또는 웹 페이지 배후에 있는 DOM의 특성에 전혀 영향을 주지 않습니다.SaaS 제품은 1년에 4회 기본 DOM 설계를 변경할 수 있기 때문에 Selenium을 사용한 견고하고 퍼포먼스 높은 테스트 방법을 지속적으로 모색할 수 있습니다(가능성이 있는 경우 Selenium을 사용한 테스트 없음 포함).
"페이지 준비 완료"에 사용하는 것은 다음과 같습니다.현재 제 모든 테스트에서 효과가 있습니다.이 접근방식은 몇 년 전 대규모 사내 Java 웹 앱에도 적용되었으며, 제가 프로젝트를 떠날 당시 1년 넘게 견고했습니다.
Driver
입니다.DefaultPageLoadTimeout
값입니다.
public IWebDriver Driver { get; private set; }
// ...
const int GlobalPageLoadTimeOutSecs = 10;
static readonly TimeSpan DefaultPageLoadTimeout =
new TimeSpan((long) (10_000_000 * GlobalPageLoadTimeOutSecs));
Driver = new FirefoxDriver();
내용에서는 기다림의 를 ''라는 .PageReady
준비 Ajax, 가 있습니다 (셀레늄 문서 준비, Ajax, Ajax, Ajax)
- 코드를 포함한 페이지를 로드하다
- 코드를 사용하여 Ajax를 통해 어딘가에서 데이터를 로드합니다.
- 아마도 애니메이션을 사용하여 데이터를 제시하다
1과 2 사이에 DOM 비교 접근법 같은 것을 사용하여 견고성을 한 층 더 추가할 수 있습니다.
public void PageReady()
{
DocumentReady();
AjaxReady();
AnimationsReady();
}
private void DocumentReady()
{
WaitForJavascript(script: "return document.readyState", result: "complete");
}
private void WaitForJavascript(string script, string result)
{
new WebDriverWait(Driver, DefaultPageLoadTimeout).Until(
d => ((IJavaScriptExecutor) d).ExecuteScript(script).Equals(result));
}
private void AjaxReady()
{
WaitForJavascript(script: "return jQuery.active.toString()", result: "0");
}
private void AnimationsReady()
{
WaitForJavascript(script: "return $(\"animated\").length.toString()", result: "0");
}
어떻게 해야 할지 모르겠지만, 내 경우 파이어폭스 탭에 표시된 FAVICON과 페이지 끝 로드 및 렌더링이 일치합니다.
따라서 웹브라우저에서 favicon 이미지를 얻을 수 있다면 웹 페이지는 완전히 로딩되어 있습니다.
하지만 어떻게 하면...
암묵적인 대기 방식을 사용하는 것이 좋습니다.
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
Selenium c# Webdriver 의 답변을 참조해 주세요. 요소가 존재할 때까지 대기
방법은 다음과 같습니다.
new WebDriverWait(driver, 20).until(
ExpectedConditions.jsReturnsValue(
"return document.readyState === 'complete' ? true : false"));
언급URL : https://stackoverflow.com/questions/10720325/selenium-webdriver-wait-for-complex-page-with-javascript-to-load
'programing' 카테고리의 다른 글
mysql 사용자 생성(존재하지 않는 경우) (0) | 2023.01.23 |
---|---|
레퍼런스:가변 범위란 무엇이며, 어디에서 접근할 수 있는 변수와 "정의되지 않은 변수" 오류는 무엇입니까? (0) | 2023.01.23 |
MySQL에서 문자열을 최신 상태로 변환하는 방법 (0) | 2023.01.23 |
선택 쿼리에서 테이블을 업데이트하는 방법 (0) | 2023.01.23 |
MySQL - 삽입 오류 무시: 중복 항목 (0) | 2023.01.23 |