Java Selenium-WebDriver에서 일하고 있습니다. 나는 추가했다
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
과
WebElement textbox = driver.findElement(By.id("textbox"));
내 응용 프로그램이 사용자 인터페이스를로드하는 데 몇 초가 걸리기 때문입니다. 그래서 2 초를 implicitwait로 설정했습니다. 하지만 요소 텍스트 상자를 찾을 수 없습니다.
그런 다음 추가 Thread.sleep(2000);
이제 잘 작동합니다. 어느 것이 더 좋은 방법입니까?
답변
음, 대기에는 명시 적 대기와 암시 적 대기라는 두 가지 유형이 있습니다. 명시 적 대기의 개념은
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
:
시간 초과 및 폴링 간격을 즉시 구성 할 수있는 Wait 인터페이스의 구현입니다. 각 FluentWait 인스턴스는 조건을 확인하는 빈도뿐 아니라 조건을 기다리는 최대 시간을 정의합니다. 또한 사용자는 페이지의 요소를 검색 할 때 NoSuchElementExceptions와 같이 대기하는 동안 특정 유형의 예외를 무시하도록 대기를 구성 할 수 있습니다.여기에서
얻을 수있는 세부 정보
fluentWait
귀하의 경우 사용은 다음과 같습니다.
WebElement textbox = fluentWait(By.id("textbox"));
이 접근법은 얼마나 많은 시간을 기다려야하는지 정확히 알지 못하기 때문에 IMHO가 더 좋습니다. 폴링 간격에서 요소 존재를 확인할 임의의 시간 값을 설정할 수 있습니다. 문안 인사.
답변
이 스레드는 조금 오래되었지만 현재 수행중인 작업 (진행중인 작업)을 게시 할 것이라고 생각했습니다.
여전히 시스템 부하가 true
높고 제출 버튼 (예 : login.jsp)을 클릭하면 세 가지 조건 (아래 참조)이 모두 반환 되지만 다음 페이지 (예 : home.jsp)는 반환 되지 않습니다. t는 아직로드를 시작했습니다.
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를 정의했습니다 (아래에 3 개). 이 예에서 예상되는 세 가지 조건에는 document.readyState = ‘complete’, “wait_dialog”없음 및 ‘spinners’없음 (비동기 데이터가 요청됨을 나타내는 요소)가 포함됩니다.
일반적으로 모든 웹 페이지에 첫 번째 항목 만 적용 할 수 있습니다.
/**
* 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
);
다음 클래스에도 사전 정의 된 ExpectedConditions가 있습니다. org.openqa.selenium.support.ui.ExpectedConditions
답변
webdriverJs (node.js)를 사용하는 경우
driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
driver.sleep(5000);
});
위의 코드는 브라우저가 버튼을 클릭 한 후 5 초 동안 기다리게합니다.
답변
사용 Thread.sleep(2000);
은 무조건 기다립니다. 테스트가 더 빨리로드 되더라도 기다려야합니다. 따라서 원칙적으로 사용 implicitlyWait
하는 것이 더 나은 솔루션입니다.
그러나 implicitlyWait
귀하의 경우에는 왜 작동하지 않는지 알 수 없습니다. findElement
예외가 발생하기 전에 실제로 2 초가 걸리는지 측정 했습니까? 그렇다면 이 답변에 설명 된대로 WebDriver의 조건부 대기를 사용해 볼 수 있습니까?
답변
사용자 지정 조건을 사용하고 싶습니다. 다음은 Python의 일부 코드입니다.
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
목록을 반환합니다-비어 있는지 여부를 확인하기 만하면됩니다.
답변
클릭이 차단되는 것처럼 보입니까? -WebDriverJS를 사용하는 경우 기다리는 또 다른 방법이 있습니다.
driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
driver.getPageSource().then(function(source) {
console.log(source);
});
});
위의 코드는 버튼을 클릭 한 후 다음 페이지가로드 될 때까지 기다린 후 다음 페이지의 소스를 가져옵니다.
답변
암시 적으로 대기 및 Thread.sleep 둘 다 동기화에만 사용됩니다. 그러나 차이점은 암시 적으로 전체 프로그램을 기다릴 수 있지만 Thread.sleep은 해당 단일 코드에서만 작동합니다. 여기에서 내 제안은 프로그램에서 암시 적으로 한 번 대기하는 것입니다. 웹 페이지가 새로 고쳐질 때마다 그 시간에 Thread.sleep을 사용하십시오. 훨씬 나아질 것입니다. 🙂
내 코드는 다음과 같습니다.
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();
}
}