Để thêm vào câu trả lời của @ jarib, tôi đã thực hiện một số phương pháp mở rộng giúp loại bỏ điều kiện cuộc đua.
Đây là thiết lập của tôi:
Tôi có một lớp được gọi là "Driver.cs". Nó chứa một lớp tĩnh chứa đầy các phương thức mở rộng cho trình điều khiển và các hàm tĩnh hữu ích khác.
Đối với các phần tử tôi thường cần truy xuất, tôi tạo một phương thức mở rộng như sau:
public static IWebElement SpecificElementToGet(this IWebDriver driver) {
return driver.FindElement(By.SomeSelector("SelectorText"));
}
Điều này cho phép bạn truy xuất phần tử đó từ bất kỳ lớp kiểm tra nào với mã:
driver.SpecificElementToGet();
Bây giờ, nếu điều này dẫn đến một StaleElementReferenceException
, tôi có phương thức tĩnh sau trong lớp trình điều khiển của mình:
public static void WaitForDisplayed(Func<IWebElement> getWebElement, int timeOut)
{
for (int second = 0; ; second++)
{
if (second >= timeOut) Assert.Fail("timeout");
try
{
if (getWebElement().Displayed) break;
}
catch (Exception)
{ }
Thread.Sleep(1000);
}
}
Tham số đầu tiên của hàm này là bất kỳ hàm nào trả về đối tượng IWebEuity. Tham số thứ hai là thời gian chờ tính bằng giây (mã cho thời gian chờ đã được sao chép từ Selenium IDE cho FireFox). Mã có thể được sử dụng để tránh ngoại lệ phần tử cũ theo cách sau:
MyTestDriver.WaitForDisplayed(driver.SpecificElementToGet,5);
Đoạn mã trên sẽ gọi driver.SpecificElementToGet().Displayed
cho đến khi driver.SpecificElementToGet()
ném không có ngoại lệ và .Displayed
đánh giá true
và 5 giây chưa trôi qua. Sau 5 giây, bài kiểm tra sẽ thất bại.
Mặt khác, để chờ một phần tử không xuất hiện, bạn có thể sử dụng chức năng sau theo cách tương tự:
public static void WaitForNotPresent(Func<IWebElement> getWebElement, int timeOut) {
for (int second = 0;; second++) {
if (second >= timeOut) Assert.Fail("timeout");
try
{
if (!getWebElement().Displayed) break;
}
catch (ElementNotVisibleException) { break; }
catch (NoSuchElementException) { break; }
catch (StaleElementReferenceException) { break; }
catch (Exception)
{ }
Thread.Sleep(1000);
}
}