回答:
または、暗黙の待機を使用することもできます。
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
暗黙的な待機とは、1つまたは複数の要素がすぐに利用できない場合に要素を見つけようとするときに、DOMを一定時間ポーリングするようにWebDriverに指示することです。デフォルト設定は0です。一度設定すると、WebDriverオブジェクトインスタンスの存続期間中、暗黙の待機が設定されます。
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
Mike Kwanが提供するソリューションを使用すると、暗黙的な待機がすべてのFindElement呼び出しで使用されるため、テスト全体のパフォーマンスに影響を与える可能性があります。 多くの場合、要素が存在しないときに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();
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));
うまくいきます。他の誰かがまだ見つからないランダムな要素を取得した場合に備えて準備します。
あなたも使うことができます
ExpectedConditions.ElementExists
したがって、そのような要素の可用性を検索します
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秒で、に書き込まれたメッセージは1つだけです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でWebdriver形式を選択しても、clickAndWaitコマンドは変換されません。これが回避策です。以下にウェイトラインを追加します。現実的には、問題はこの前に発生したクリックまたはイベントでした-私のC#コードの1行目。しかし、実際には、「By」オブジェクトを参照するアクションの前に、WaitForElementがあることを確認してください。
HTMLコード:
<a href="http://www.google.com">xxxxx</a>
C#/ NUnitコード:
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();
要素が変更されるまで、あまり長く待ちたくない。このコードでは、Webドライバーは最大2秒待ってから続行します。
WebDriverWait wait = new WebDriverWait(driver、TimeSpan.FromMilliseconds(2000)); wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(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;
}
};
}
これは、明示的な待機を使用して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
、本当の場合は使用するかどうかを確認しますawait Task.Delay
。それは本当に効率的ではありません。
すでに投稿された複数のソリューションがうまく機能しているのがわかります!しかし、誰かが何か他のものが必要な場合に備えて、私が個人的にセレンC#で使用した2つのソリューションを投稿して、要素が存在するかどうかをテストすると思いました!よろしくお願いいたします。
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;
}
}
これが2番目です
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;
}
}
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));
最初の答えは良いです、私の問題は、未処理の例外がWebドライバーを適切に閉じず、私が使用したのと同じ最初の値である1秒を維持することでした。
同じ問題が発生した場合
restart you visual studio
そしてそれをall the exceptions are handled
適切に確認します。
TimeSpan.FromSeconds(5)
です。IMOがより明確になります