Selenium c # Webdo: Chờ cho đến khi yếu tố có mặt


185

Tôi muốn đảm bảo rằng một phần tử có mặt trước khi webdo bắt đầu thực hiện công cụ.

Tôi đang cố gắng để làm một cái gì đó như thế này để làm việc:

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
wait.Until(By.Id("login"));

Tôi chủ yếu đấu tranh làm thế nào để thiết lập chức năng anynomous ..


3
FYI - nó sạch hơn để xây dựng thời gian của bạn như thế này TimeSpan.FromSeconds(5). Nó làm cho nó rõ ràng hơn IMO
Kolob Canyon

Câu trả lời:


159

Ngoài ra, bạn có thể sử dụng chờ đợi ngầm:

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

Chờ đợi ngầm là yêu cầu WebDriver thăm dò DOM trong một khoảng thời gian nhất định khi cố gắng tìm một phần tử hoặc phần tử nếu chúng không có sẵn ngay lập tức. Cài đặt mặc định là 0. Sau khi được đặt, chờ đợi ngầm định được đặt cho vòng đời của đối tượng WebDriver.


5
cảm ơn, cú pháp mới là: driver.manage (). timeouts (). ngầmlyWait (10, TimeUnit.SECONDS);
Reda

20
@RedaBalkouch, cú pháp Mike sử dụng trong Câu trả lời của mình là chính xác. Đó là C #
Diemo

3
Nếu bạn chọn sử dụng chờ đợi ngầm, hãy cẩn thận không sử dụng chờ đợi rõ ràng. Điều đó có thể gây ra một số hành vi không thể đoán trước dẫn đến kết quả kiểm tra xấu. Nói chung, tôi sẽ khuyên bạn nên sử dụng chờ đợi rõ ràng hơn chờ đợi ngầm.
mrfreester

7
Phương pháp này hiện không được chấp nhận, thay vào đó, bạn nên sử dụng thuộc tính ImplicitWait:Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
Samuel Rondeau-Millaire

1
Tôi đã sử dụng phương pháp được cung cấp và thấy phương pháp này không được chấp nhận như Samuel đã chỉ ra. Kiểm tra sự tồn tại của một mặt hàng hiện đang chờ đến thời gian quy định.
Jim Scott

279

Sử dụng giải pháp do Mike Kwan cung cấp có thể có tác động đến hiệu suất thử nghiệm tổng thể, vì chờ đợi ngầm sẽ được sử dụng trong tất cả các cuộc gọi FindEuity. Nhiều lần bạn sẽ muốn FindEuity bị lỗi ngay lập tức khi không có phần tử (bạn đang kiểm tra trang không đúng định dạng, phần tử bị thiếu, v.v.). Với sự chờ đợi ngầm, các hoạt động này sẽ đợi cho đến khi hết thời gian chờ trước khi ném ngoại lệ. Chờ đợi ngầm định được đặt thành 0 giây.

Tôi đã viết một phương thức mở rộng nhỏ cho IWebDriver để thêm tham số thời gian chờ (tính bằng giây) cho FindElement()phương thức. Nó khá tự giải thích:

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);
    }
}

Tôi đã không lưu trữ đối tượng WebDriverWait vì việc tạo ra nó rất rẻ, tiện ích mở rộng này có thể được sử dụng đồng thời cho các đối tượng WebDriver khác nhau và tôi chỉ thực hiện tối ưu hóa khi thực sự cần thiết.

Cách sử dụng rất đơn giản:

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();

113
Trong trường hợp ai đó thắc mắc, WebDriverWaitlà từ OpenQA.Selenium.Support.UIkhông gian tên và đi kèm trong một gói riêng được gọi Selenium WebDriver Support Classestrên NuGet
Andy

5
@Ved tôi có thể hôn bạn <3 đang tìm kiếm nó trong một dll khác: D
Adween

1
@Loudenvier Vui lòng in đậm dòng đầu tiên để dễ nhận thấy hơn. Đặc biệt vì nó không phải là câu trả lời được chấp nhận, mặc dù là một cách tiếp cận tốt hơn và chính xác hơn.
Rick

5
Selenium WebDriver Support Classeshiện được xuất hiện trên NuGet với tên "Selenium.Support" , phiên bản hiện tại là 3.4.0
Eric F.

1
Tôi vẫn còn rất nhiều lỗi cho đến khi tôi sử dụng dòng này return wait.Until(ExpectedConditions.ElementToBeClickable(by));và nó hoạt động rất tốt. Đứng lên trong trường hợp bất cứ ai khác nhận được các yếu tố ngẫu nhiên không tìm thấy vẫn còn.
tìm kiếm

84

Bạn cũng có thể dùng

ExpectedConditions.EuityExists

Vì vậy, bạn sẽ tìm kiếm một yếu tố sẵn có như thế

new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));

Nguồn


1
Đồng ý, điều này hữu ích hơn nhiều so với thời gian chờ đơn thuần (trong trường hợp bạn đang tải động một đối tượng).
keithl8041

5
Trong khi điều này hoạt động. Bây giờ nó được đánh dấu là không dùng nữa, vì vậy nên tránh.
Adam Garner

3
Đây là cách tiếp cận mới (không được phản đối): stackoverflow.com/a/49867605/331281
Dejan

1
Lưu ý rằng, tại thời điểm này, DotNetSeleniumExtras.WaitHelpers(được gọi là @Dejan ở trên) "không được duy trì, các vấn đề sẽ không được khắc phục, PR sẽ không được chấp nhận". (nguồn: github.com/SeleniumHQ/selenium/issues/, ). Nhà xuất bản của nó đang tìm kiếm một người bảo trì để tiếp nhận nó từ anh ta.
urig

30

Đây là một biến thể của giải pháp @ Loudenvier cũng hoạt động để có được nhiều yếu tố:

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);
    }
}

7
Đẹp! Tôi vừa mới thêm cái này vào thư viện của riêng tôi! Đó là vẻ đẹp của việc chia sẻ mã !!!
Lâu đài

1
Tôi muốn đề nghị một bổ sung cho điều đó. Bạn có thể bắt giải pháp NoSuchEuity và trả về null trong trường hợp đó. Sau đó, bạn có thể tạo một phương thức mở rộng có tên .exists trả về true trừ khi IWebEuity là null.
Brantley Blanchard

17

Lấy cảm hứng từ giải pháp của Loudenvier, đây là một phương thức mở rộng hoạt động cho tất cả các đối tượng ISearchContext, không chỉ IWebDriver, một chuyên ngành trước đây. Phương pháp này cũng hỗ trợ chờ cho đến khi phần tử được hiển thị.

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;
        });
    }
}

Ví dụ sử dụng:

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();

1
Nếu bạn đã đặt một sự chờ đợi ngầm định như vậy _webDriver.Manage().Timeouts().ImplicitlyWait(Timeout);vẫn sẽ vượt qua giá trị hết thời gian bạn đặt ở đây.
howcheng 18/03/2015

Điều này dường như không làm việc cho tôi ...? Tôi đã thêm một Stopwatchcuộc gọi xung quanh phương thức mở rộng và Console.WriteLine()bên trong lambda được gửi đến Until(). Đồng hồ bấm giờ đo gần như chính xác 60 giây và chỉ có một tin nhắn được viết Console. Am i thiếu cái gì ở đây?
urig

10

Tôi nhầm lẫn chức năng bất thường với vị ngữ. Đây là một phương pháp trợ giúp nhỏ:

   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)));
    }

5

Bạn có thể tìm ra một cái gì đó như thế này trong C #.

Đây là những gì tôi đã sử dụng trong JUnit - Selenium

WebDriverWait wait = new WebDriverWait(driver, 100);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));

Nhập các gói liên quan


1
Tôi cố gắng sử dụng ngày hôm nay và VS.net được đem lại cho tôi cảnh báo: lớp OpenQA.Selenium.Support.UI.ExpectedConditions đã được đánh dấu "phản đối" và được "di cư đến DotNetSeleniumExtras" repo trên github.com/DotNetSeleniumTools
Jeff Mergler

3
//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"));
});

3
public bool doesWebElementExist(string linkexist)
{
     try
     {
        driver.FindElement(By.XPath(linkexist));
        return true;
     }
     catch (NoSuchElementException e)
     {
        return false;
     }
}

Đoạn mã trên là để kiểm tra xem một phần tử cụ thể có mặt hay không.
Madhu

2

Lệnh clickAndWait không được chuyển đổi khi bạn chọn định dạng Webdo trong Selenium IDE. Đây là cách giải quyết. Thêm dòng chờ bên dưới. Trên thực tế, vấn đề là nhấp chuột hoặc sự kiện đã xảy ra trước dòng này - dòng 1 trong mã C # của tôi. Nhưng thực sự, chỉ cần đảm bảo rằng bạn có WaitForEuity trước bất kỳ hành động nào mà bạn đang tham chiếu một đối tượng "Bởi".

Mã HTML:

<a href="http://www.google.com">xxxxx</a>

Mã C # / NUnit:

driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();

2

Con trăn

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'))

từ EC, bạn có thể chọn các điều kiện khác cũng như thử điều này: http://selenium-python.readthedocs.org/api.html#module-selenium.webdo.support.azed_conditions


Câu hỏi này được gắn thẻ C #, không phải Python. Câu trả lời này không liên quan.
Người dùng

2

Hãy thử mã này:

 New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)

4
Bạn nên giải thích những gì bạn đã làm và tại sao điều này giải quyết vấn đề. Và hãy định dạng mã của bạn.
Hering

1

Chờ đợi

public static  WebDriverWait wait = new WebDriverWait(driver, 60);

Thí dụ:

wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));

1

Đã sử dụng Rn222 và Aknuds1 để sử dụng ISearchContext trả về một phần tử hoặc danh sách. Và một số phần tử tối thiểu có thể được chỉ định:

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);
    }

}

Ví dụ sử dụng:

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();

1

Bạn không muốn đợi quá lâu trước khi phần tử thay đổi. Trong mã này, webler đợi tối đa 2 giây trước khi tiếp tục.

WebDriverWait Wait = new WebDriverWait (trình điều khiển, TimeSpan.FromMilliseconds (2000));
chờ đợi.Until (Dự kiến


1

Vì tôi đang tách các định nghĩa thành phần trang và các kịch bản kiểm tra trang bằng cách sử dụng IWebE bổ sung cho khả năng hiển thị có thể được thực hiện như thế này:

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;
        }
    };
}

1

Đây là chức năng có thể sử dụng lại để chờ một phần tử có trong DOM bằng cách sử dụng Chờ đợi.

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;
        }
    });
}

Chào mừng bạn đến với Stack Overflow, vui lòng không đăng câu trả lời chỉ có mã.
JJ cho Minh bạch và Monica

0

Chúng ta có thể đạt được điều đó như thế này:

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;
    }
}

0

WebDriverWait sẽ không có hiệu lực.

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

Điều này sẽ ngay lập tức ném một ngoại lệ khi trang "tương tác". Tôi không biết tại sao nhưng thời gian chờ hoạt động như thể không tồn tại.

Có lẽ SeleniumExtras.WaitHelpershoạt động nhưng tôi đã không thử. Nó chính thức nhưng được chia thành một gói nuget khác. Bạn có thể tham khảo C # Selenium 'ExpectedConditions đã lỗi thời' .

Bản thân tôi đang sử dụng FindElementsvà kiểm tra xem Count == 0, nếu đúng, sử dụng await Task.Delay. Nó thực sự không hiệu quả lắm.


0

Bạn có thể sử dụng như sau

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
wait.Until(ExpectedConditions.ElementToBeClickable((By.Id("login")));

-1

Tôi thấy nhiều giải pháp đã được đăng mà làm việc tuyệt vời! Tuy nhiên, chỉ trong trường hợp bất kỳ ai cần thứ gì khác, tôi nghĩ rằng tôi sẽ đăng hai giải pháp mà cá nhân tôi đã sử dụng trong selenium C # để kiểm tra xem có yếu tố nào không! Hy vọng nó sẽ giúp, chúc mừng!

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; 
    }

}

Đây là cái thứ hai

    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
 new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
   Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));

ExpectedConditions không được dùng nữa
GELR

-1

Câu trả lời đầu tiên là tốt, vấn đề của tôi là các ngoại lệ chưa được xử lý đã không đóng trình điều khiển web đúng cách và nó vẫn giữ nguyên giá trị đầu tiên tôi đã sử dụng là 1 giây.

Nếu bạn gặp vấn đề tương tự

restart you visual studiovà đảm bảo all the exceptions are handledđúng cách.


Đến bây giờ bạn nên biết rằng không có thứ tự nào cho câu trả lời trong Stack Overflow, vì vậy không có "câu trả lời đầu tiên"
Antti Haapala

-2

Đã tìm kiếm làm thế nào để chờ đợi trong Selenium cho điều kiện, đã rơi vào chủ đề này và đây là những gì tôi sử dụng bây giờ:

    WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10));
    wait.Until(d => ReadCell(row, col) != "");

ReadCell(row, col) != ""có thể là bất kỳ điều kiện. Thích cách này vì:

  • nó là của tôi
  • cho phép nội tuyến
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.