답변:
또는 암시 적 대기를 사용할 수 있습니다.
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
암시 적 대기는 요소를 즉시 사용할 수없는 경우 요소를 찾으려고 할 때 WebDriver에 일정 시간 동안 DOM을 폴링하도록 지시하는 것입니다. 기본 설정은 0입니다. 일단 설정된 후 내재 된 대기는 WebDriver 오브젝트 인스턴스의 수명 동안 설정됩니다.
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
암시 적 대기는 모든 FindElement 호출에 사용되므로 Mike Kwan이 제공 한 솔루션을 사용하면 전체 테스트 성능에 영향을 줄 수 있습니다. 요소가 존재하지 않을 때 (잘못된 페이지, 누락 된 요소 등을 테스트하는 경우) FindElement가 즉시 실패하기를 원하는 경우가 많습니다. 암시 적 대기를 사용하면 이러한 작업은 예외가 발생하기 전에 전체 시간 초과가 만료 될 때까지 기다립니다. 기본 암시 적 대기는 0 초로 설정됩니다.
메소드에 시간 초과 (초) 매개 변수를 추가하는 IWebDriver에 약간의 확장 메소드를 작성했습니다 FindElement()
. 매우 설명이 필요합니다.
public static class WebDriverExtensions
{
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}
}
WebDriverWait 객체는 생성 비용이 매우 저렴하므로 캐시하지 않았으며이 확장은 다른 WebDriver 객체에 동시에 사용될 수 있으며 궁극적으로 필요할 때만 최적화를 수행합니다.
사용법은 간단합니다.
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost/mypage");
var btn = driver.FindElement(By.CssSelector("#login_button"));
btn.Click();
var employeeLabel = driver.FindElement(By.CssSelector("#VCC_VSL"), 10);
Assert.AreEqual("Employee", employeeLabel.Text);
driver.Close();
WebDriverWait
점이 있다면 OpenQA.Selenium.Support.UI
네임 스페이스에서 왔으며 Selenium WebDriver Support Classes
NuGet 이라는 별도의 패키지로 제공됩니다.
Selenium WebDriver Support Classes
은 NuGet에 "Selenium.Support" 로 나타나며 현재 버전은 3.4.0입니다.
return wait.Until(ExpectedConditions.ElementToBeClickable(by));
지금은 잘 작동합니다. 다른 사람이 여전히 발견되지 않은 임의의 요소를 얻는 경우를 대비하여 진행합니다.
당신은 또한 사용할 수 있습니다
예상되는 조건. 요소
그래서 당신은 그런 요소 가용성을 검색 할 것입니다
new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));
DotNetSeleniumExtras.WaitHelpers
(위의 @Dejan에 의해 언급 됨) "유지되지 않으며, 문제가 해결되지 않으며, PR은 수락되지 않습니다." (출처 : github.com/SeleniumHQ/selenium/issues/… ). 그 출판사는 그에게서 그것을 인수하기 위해 관리자를 찾고 있습니다.
다음은 여러 요소를 가져 오는 데 사용되는 @Loudenvier 솔루션의 변형입니다.
public static class WebDriverExtensions
{
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}
public static ReadOnlyCollection<IWebElement> FindElements(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => (drv.FindElements(by).Count > 0) ? drv.FindElements(by) : null);
}
return driver.FindElements(by);
}
}
Loudenvier의 솔루션에서 영감을 얻은 다음은 전자를 전문으로하는 IWebDriver뿐만 아니라 모든 ISearchContext 객체에서 작동하는 확장 메서드입니다. 이 방법은 요소가 표시 될 때까지 대기하는 것도 지원합니다.
static class WebDriverExtensions
{
/// <summary>
/// Find an element, waiting until a timeout is reached if necessary.
/// </summary>
/// <param name="context">The search context.</param>
/// <param name="by">Method to find elements.</param>
/// <param name="timeout">How many seconds to wait.</param>
/// <param name="displayed">Require the element to be displayed?</param>
/// <returns>The found element.</returns>
public static IWebElement FindElement(this ISearchContext context, By by, uint timeout, bool displayed=false)
{
var wait = new DefaultWait<ISearchContext>(context);
wait.Timeout = TimeSpan.FromSeconds(timeout);
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
return wait.Until(ctx => {
var elem = ctx.FindElement(by);
if (displayed && !elem.Displayed)
return null;
return elem;
});
}
}
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
var btn = main.FindElement(By.Id("button"));
btn.Click();
var dialog = main.FindElement(By.Id("dialog"), 5, displayed: true);
Assert.AreEqual("My Dialog", dialog.Text);
driver.Close();
_webDriver.Manage().Timeouts().ImplicitlyWait(Timeout);
를 설정 한 경우 여기에서 설정 한 시간 초과 값보다 우선합니다.
Stopwatch
확장 메서드에 대한 호출 주위를 추가하고 에 Console.WriteLine()
람다를 보냈습니다 Until()
. 스톱워치는 거의 정확히 60 초를 측정했으며 하나의 메시지 만 기록되었습니다 Console
. 여기에 뭔가 빠졌습니까?
C #에서 이와 같은 것을 찾을 수 있습니다.
이것이 내가 JUnit에서 사용한 것입니다-Selenium
WebDriverWait wait = new WebDriverWait(driver, 100);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));
관련 패키지 가져 오기
//wait up to 5 seconds with no minimum for a UI element to be found
WebDriverWait wait = new WebDriverWait(_pagedriver, TimeSpan.FromSeconds(5));
IWebElement title = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.ClassName("MainContentHeader"));
});
Selenium IDE에서 웹 드라이버 형식을 선택하면 clickAndWait 명령이 변환되지 않습니다. 해결 방법은 다음과 같습니다. 아래에 대기 줄을 추가하십시오. 사실, 문제는 C # 코드에서 1 행 전에 발생한 클릭 또는 이벤트였습니다. 그러나 실제로는 "By"객체를 참조하는 작업 전에 WaitForElement가 있는지 확인하십시오.
HTML 코드 :
<a href="http://www.google.com">xxxxx</a>
C # / N 단위 코드 :
driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
driver.find_element_by_id('someId').click()
WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, 'someAnotherId'))
EC에서 다른 조건을 선택할 수도 있습니다. http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions
이 코드를 사용해보십시오 :
New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)
Rn222 및 Aknuds1을 사용하여 단일 요소 또는 목록을 반환하는 ISearchContext를 사용했습니다. 최소 요소 수를 지정할 수 있습니다.
public static class SearchContextExtensions
{
/// <summary>
/// Method that finds an element based on the search parameters within a specified timeout.
/// </summary>
/// <param name="context">The context where this is searched. Required for extension methods</param>
/// <param name="by">The search parameters that are used to identify the element</param>
/// <param name="timeOutInSeconds">The time that the tool should wait before throwing an exception</param>
/// <returns> The first element found that matches the condition specified</returns>
public static IWebElement FindElement(this ISearchContext context, By by, uint timeOutInSeconds)
{
if (timeOutInSeconds > 0)
{
var wait = new DefaultWait<ISearchContext>(context);
wait.Timeout = TimeSpan.FromSeconds(timeOutInSeconds);
return wait.Until<IWebElement>(ctx => ctx.FindElement(by));
}
return context.FindElement(by);
}
/// <summary>
/// Method that finds a list of elements based on the search parameters within a specified timeout.
/// </summary>
/// <param name="context">The context where this is searched. Required for extension methods</param>
/// <param name="by">The search parameters that are used to identify the element</param>
/// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
/// <returns>A list of all the web elements that match the condition specified</returns>
public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new DefaultWait<ISearchContext>(context);
wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
return wait.Until<IReadOnlyCollection<IWebElement>>(ctx => ctx.FindElements(by));
}
return context.FindElements(by);
}
/// <summary>
/// Method that finds a list of elements with the minimum amount specified based on the search parameters within a specified timeout.<br/>
/// </summary>
/// <param name="context">The context where this is searched. Required for extension methods</param>
/// <param name="by">The search parameters that are used to identify the element</param>
/// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
/// <param name="minNumberOfElements">
/// The minimum number of elements that should meet the criteria before returning the list <para/>
/// If this number is not met, an exception will be thrown and no elements will be returned
/// even if some did meet the criteria
/// </param>
/// <returns>A list of all the web elements that match the condition specified</returns>
public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds, int minNumberOfElements)
{
var wait = new DefaultWait<ISearchContext>(context);
if (timeoutInSeconds > 0)
{
wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
}
// Wait until the current context found the minimum number of elements. If not found after timeout, an exception is thrown
wait.Until<bool>(ctx => ctx.FindElements(by).Count >= minNumberOfElements);
//If the elements were successfuly found, just return the list
return context.FindElements(by);
}
}
사용법 예 :
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
// It can be now used to wait when using elements to search
var btn = main.FindElement(By.Id("button"),10);
btn.Click();
//This will wait up to 10 seconds until a button is found
var button = driver.FindElement(By.TagName("button"),10)
//This will wait up to 10 seconds until a button is found, and return all the buttons found
var buttonList = driver.FindElements(By.TagName("button"),10)
//This will wait for 10 seconds until we find at least 5 buttons
var buttonsMin= driver.FindElements(By.TagName("button"), 10, 5);
driver.Close();
가시성을 위해 이미 찾은 IWebElement를 사용하여 페이지 요소 정의와 페이지 테스트 시나리오를 분리하므로 다음과 같이 수행 할 수 있습니다.
public static void WaitForElementToBecomeVisibleWithinTimeout(IWebDriver driver, IWebElement element, int timeout)
{
new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until(ElementIsVisible(element));
}
private static Func<IWebDriver, bool> ElementIsVisible(IWebElement element)
{
return driver => {
try
{
return element.Displayed;
}
catch(Exception)
{
// If element is null, stale or if it cannot be located
return false;
}
};
}
이것은 명시 적 대기를 사용하여 DOM에 존재하는 요소를 기다리는 재사용 가능한 함수입니다.
public void WaitForElement(IWebElement element, int timeout = 2)
{
WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromMinutes(timeout));
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException));
wait.Until<bool>(driver =>
{
try
{
return element.Displayed;
}
catch (Exception)
{
return false;
}
});
}
우리는 이것을 다음과 같이 달성 할 수 있습니다 :
public static IWebElement WaitForObject(IWebDriver DriverObj, By by, int TimeOut = 30)
{
try
{
WebDriverWait Wait1 = new WebDriverWait(DriverObj, TimeSpan.FromSeconds(TimeOut));
var WaitS = Wait1.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.PresenceOfAllElementsLocatedBy(by));
return WaitS[0];
}
catch (NoSuchElementException)
{
Reports.TestStep("Wait for Element(s) with xPath was failed in current context page.");
throw;
}
}
WebDriverWait
적용되지 않습니다.
var driver = new FirefoxDriver(
new FirefoxOptions().PageLoadStrategy = PageLoadStrategy.Eager
);
driver.Navigate().GoToUrl("xxx");
new WebDriverWait(driver, TimeSpan.FromSeconds(60))
.Until(d => d.FindElement(By.Id("xxx"))); // a tag that close to the end
페이지가 "대화 형"이면 즉시 예외가 발생합니다. 이유를 모르지만 시간 초과는 존재하지 않는 것처럼 작동합니다.
아마도 SeleniumExtras.WaitHelpers
효과가 있지만 시도하지 않았습니다. 공식이지만 다른 nuget 패키지로 분리되었습니다. C # Selenium 'ExpectedConditions is obsolete'를 참조 할 수 있습니다 .
내 자신이 사용 FindElements
하고 있으며 Count == 0
true 인 경우 사용 하는지 확인하십시오 await Task.Delay
. 정말 효율적이지 않습니다.
여러 솔루션이 이미 게시되어 효과적입니다. 그러나 누군가 다른 것이 필요한 경우를 대비하여 셀레늄 C #에서 개인적으로 사용하는 두 가지 솔루션을 게시하여 요소가 있는지 테스트한다고 생각했습니다! 도움이 되길 바랍니다.
public static class IsPresent
{
public static bool isPresent(this IWebDriver driver, By bylocator)
{
bool variable = false;
try
{
IWebElement element = driver.FindElement(bylocator);
variable = element != null;
}
catch (NoSuchElementException){
}
return variable;
}
}
여기 두 번째입니다
public static class IsPresent2
{
public static bool isPresent2(this IWebDriver driver, By bylocator)
{
bool variable = true;
try
{
IWebElement element = driver.FindElement(bylocator);
}
catch (NoSuchElementException)
{
variable = false;
}
return variable;
}
}
첫 번째 대답은 훌륭합니다. 제 문제는 처리되지 않은 예외 로 인해 웹 드라이버가 제대로 닫히지 않았 으며 사용했던 첫 번째 값과 동일한 1 초를 유지한다는 것입니다.
같은 문제가 발생하면
restart you visual studio
그 보장 all the exceptions are handled
이 제대로.
TimeSpan.FromSeconds(5)
. 보다 분명한 IMO