셀레늄 C # 웹 드라이버 : 요소가 나타날 때까지 기다립니다
웹 드라이버가 작업을 시작하기 전에 요소가 있는지 확인하고 싶습니다.
다음과 같이 작동하려고합니다.
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
wait.Until(By.Id("login"));
나는 주로 임의의 기능을 설정하는 방법을 고심하고 있습니다.
또는 암시 적 대기를 사용할 수 있습니다.
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
암시 적 대기는 요소를 즉시 사용할 수없는 경우 요소를 찾으려고 할 때 WebDriver에 일정 시간 동안 DOM을 폴링하도록 지시하는 것입니다. 기본 설정은 0입니다. 일단 설정된 후 내재 된 대기는 WebDriver 오브젝트 인스턴스의 수명 동안 설정됩니다.
암시 적 대기는 모든 FindElement 호출에 사용되므로 Mike Kwan이 제공 한 솔루션을 사용하면 전체 테스트 성능에 영향을 줄 수 있습니다. 요소가 존재하지 않을 때 (잘못된 페이지, 누락 된 요소 등을 테스트하는 경우) FindElement가 즉시 실패하기를 원하는 경우가 많습니다. 암시 적 대기를 사용하면 이러한 작업은 예외가 발생하기 전에 전체 시간 초과가 만료 될 때까지 기다립니다. 기본 암시 적 대기는 0 초로 설정됩니다.
FindElement () 메서드에 시간 초과 (초) 매개 변수를 추가하는 작은 확장 메서드를 IWebDriver에 작성했습니다. 매우 설명이 필요합니다.
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();
당신은 또한 사용할 수 있습니다
예상되는 조건. 요소
그래서 당신은 그런 요소 가용성을 검색 할 것입니다
new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));
다음은 여러 요소를 가져 오는 데 사용되는 @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();
임의의 기능을 술어와 혼동했습니다. 다음은 약간의 도우미 방법입니다.
WebDriverWait wait;
private void waitForById(string id)
{
if (wait == null)
wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
//wait.Until(driver);
wait.Until(d => d.FindElement(By.Id(id)));
}
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
public bool doesWebElementExist(string linkexist)
{
try
{
driver.FindElement(By.XPath(linkexist));
return true;
}
catch (NoSuchElementException e)
{
return false;
}
}
이 코드를 사용해보십시오 :
New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)
명시 적 대기
public static WebDriverWait wait = new WebDriverWait(driver, 60);
예:
wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));
요소가 변경되기 전에 너무 오래 기다리기를 원하지 않습니다. 이 코드에서 웹 드라이버는 최대 2 초 동안 기다렸다가 계속합니다.
WebDriverWait 대기 = 새로운 WebDriverWait (드라이버, TimeSpan.FromMilliseconds (2000)); wait.Until (예상되는 조건. 가시성 모든 요소로 케이드 dBy (By.Name ( "html-name")));
가시성을 위해 이미 찾은 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;
}
};
}
여러 솔루션이 이미 게시되어 효과적입니다. 그러나 누군가 다른 것이 필요하다면 셀레늄 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;
}
}
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();
우리는 이것을 다음과 같이 달성 할 수 있습니다 :
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
This would immediately throw an exception once the page is "interactive". I don't know why but the timeout acts as if not exist.
Perhaps SeleniumExtras.WaitHelpers
works but I didn't try. It's official but was split out into another nuget package. You can refer to C# Selenium 'ExpectedConditions is obsolete'.
Myself is using FindElements
and check whether Count == 0
, if true, use await Task.Delay
. It's really not quite efficient.
This is the reusable function to wait for an element present in DOM using Explicit Wait.
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;
}
});
}
Was searching how to wait in Selenium for condition, landed in this thread and here is what I use now:
WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10));
wait.Until(d => ReadCell(row, col) != "");
ReadCell(row, col) != ""
can be any condition. Like this way because:
- it's mine
- allows inlining
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));
첫 번째 대답은 훌륭합니다. 제 문제는 처리되지 않은 예외 로 인해 웹 드라이버가 제대로 닫히지 않았 으며 사용했던 첫 번째 값과 동일한 1 초를 유지한다는 것입니다.
같은 문제가 발생하면
restart you visual studio
그 보장 all the exceptions are handled
이 제대로.
참고 URL : https://stackoverflow.com/questions/6992993/selenium-c-sharp-webdriver-wait-until-element-is-present
'development' 카테고리의 다른 글
저장하는 동안 iphone Core Data Unresolved 오류 (0) | 2020.05.26 |
---|---|
5 초마다 페이지를 다시로드하는 방법? (0) | 2020.05.26 |
Java "이 언어 레벨에서 지원되지 않는 람다 표현식" (0) | 2020.05.26 |
JavaScript를 사용하여 'div'표시 / 숨기기 (0) | 2020.05.26 |
날짜 문자열이 해당 형식의 유효한 날짜인지 올바르게 판별하십시오. (0) | 2020.05.26 |