Đợi JavaScript tải Selenium

Có thể nói WebDriver thường có API chặn. Bởi vì nó là một thư viện ngoài quy trình hướng dẫn trình duyệt phải làm gì và vì nền tảng web có bản chất không đồng bộ nội tại, nên WebDriver không theo dõi trạng thái hoạt động, thời gian thực của DOM. Điều này đi kèm với một số thách thức mà chúng ta sẽ thảo luận ở đây

Theo kinh nghiệm, hầu hết các sự cố không liên tục phát sinh từ việc sử dụng Selenium và WebDriver đều liên quan đến các điều kiện tương tranh xảy ra giữa trình duyệt và hướng dẫn của người dùng. Một ví dụ có thể là người dùng hướng dẫn trình duyệt điều hướng đến một trang, sau đó gặp lỗi không có phần tử như vậy khi cố gắng tìm một phần tử

Xem xét tài liệu sau



Race Condition Example


Các hướng dẫn WebDriver có thể trông đủ ngây thơ

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  

driver.Navigate().GoToUrl("file:///race_condition.html");
IWebElement element = driver.FindElement(By.TagName("p"));
assertEquals(element.Text, "Hello from JavaScript!");
  

require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
begin
  # Navigate to URL
  driver.get 'file:///race_condition.html'

  # Get and store Paragraph Text
  search_form = driver.find_element(:css,'p').text

  "Hello from JavaScript!".eql? search_form
ensure
  driver.quit
end
  

await driver.get('file:///race_condition.html');
const element = driver.findElement(By.css('p'));
assert.strictEqual(await element.getText(), 'Hello from JavaScript!');
  

driver.get("file:///race_condition.html")
val element = driver.findElement(By.tagName("p"))
assert(element.text == "Hello from JavaScript!")
  

Vấn đề ở đây là mặc định được sử dụng trong WebDriver lắng nghe

driver.Navigate().GoToUrl("file:///race_condition.html");
IWebElement element = driver.FindElement(By.TagName("p"));
assertEquals(element.Text, "Hello from JavaScript!");
  
7 để thay đổi thành
driver.Navigate().GoToUrl("file:///race_condition.html");
IWebElement element = driver.FindElement(By.TagName("p"));
assertEquals(element.Text, "Hello from JavaScript!");
  
8 trước khi quay lại cuộc gọi để điều hướng. Vì phần tử
driver.Navigate().GoToUrl("file:///race_condition.html");
IWebElement element = driver.FindElement(By.TagName("p"));
assertEquals(element.Text, "Hello from JavaScript!");
  
9 được thêm vào sau khi tải xong tài liệu, tập lệnh WebDriver này có thể bị gián đoạn. Nó “có thể” không liên tục vì không thể đảm bảo về các yếu tố hoặc sự kiện kích hoạt không đồng bộ mà không cần chờ—hoặc chặn—đối với các sự kiện đó một cách rõ ràng

May mắn thay, tập lệnh thông thường có sẵn trên giao diện WebElement—chẳng hạn như WebElement. nhấp chuột và WebElement. sendKeys—được đảm bảo là đồng bộ, trong đó lệnh gọi hàm sẽ không trả về (hoặc lệnh gọi lại sẽ không kích hoạt trong các ngôn ngữ kiểu gọi lại) cho đến khi lệnh được hoàn thành trong trình duyệt. Các API tương tác người dùng nâng cao, Bàn phím và Chuột, là những ngoại lệ vì chúng được dự định rõ ràng là các lệnh không đồng bộ “hãy làm những gì tôi nói”

Chờ đợi là việc thực thi tác vụ tự động trôi qua trong một khoảng thời gian nhất định trước khi tiếp tục với bước tiếp theo

Để khắc phục vấn đề về điều kiện tương tranh giữa trình duyệt và tập lệnh WebDriver của bạn, hầu hết các ứng dụng khách Selenium đều gửi gói chờ. Khi sử dụng một sự chờ đợi, bạn đang sử dụng những gì thường được gọi là một

chờ đợi rõ ràng

Chờ đợi rõ ràng có sẵn cho khách hàng Selenium cho các ngôn ngữ thủ tục, mệnh lệnh. Chúng cho phép mã của bạn tạm dừng thực thi chương trình hoặc đóng băng chuỗi cho đến khi điều kiện bạn vượt qua nó được giải quyết. Điều kiện được gọi với tần suất nhất định cho đến khi hết thời gian chờ. Điều này có nghĩa là miễn là điều kiện trả về giá trị sai, nó sẽ tiếp tục cố gắng và chờ đợi

Vì các khoảng chờ rõ ràng cho phép bạn đợi một điều kiện xảy ra nên chúng rất phù hợp để đồng bộ hóa trạng thái giữa trình duyệt và DOM của nó và tập lệnh WebDriver của bạn

Để khắc phục tập lệnh lỗi của chúng tôi từ trước đó, chúng tôi có thể sử dụng thời gian chờ để lệnh gọi findElement đợi cho đến khi phần tử được thêm động từ tập lệnh đã được thêm vào DOM

WebDriver driver = new ChromeDriver();
driver.get("https://google.com/ncr");
driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER);
// Initialize and wait till element(link) became clickable - timeout in 10 seconds
WebElement firstResult = new WebDriverWait(driver, Duration.ofSeconds(10))
        .until(ExpectedConditions.elementToBeClickable(By.xpath("//a/h3")));
// Print the first result
System.out.println(firstResult.getText());
  

from selenium.webdriver.support.wait import WebDriverWait
def document_initialised(driver):
    return driver.execute_script("return initialised")

driver.navigate("file:///race_condition.html")
WebDriverWait(driver, timeout=10).until(document_initialised)
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  

driver = new ChromeDriver();
driver.Url = "https://www.google.com/ncr";
driver.FindElement(By.Name("q")).SendKeys("cheese" + Keys.Enter);

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement firstResult = wait.Until(e => e.FindElement(By.XPath("//a/h3")));

Console.WriteLine(firstResult.Text);
  

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
0

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
1

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
2

Chúng ta chuyển vào điều kiện dưới dạng tham chiếu hàm mà lệnh chờ sẽ chạy lặp lại cho đến khi giá trị trả về của nó là true. Giá trị trả về “trung thực” là bất kỳ giá trị nào có giá trị boolean true trong ngôn ngữ hiện tại, chẳng hạn như chuỗi, số, boolean, đối tượng (bao gồm WebElement) hoặc chuỗi hoặc danh sách được điền (không trống). Điều đó có nghĩa là một danh sách trống đánh giá là sai. Khi điều kiện là đúng và chờ chặn bị hủy bỏ, giá trị trả về từ điều kiện sẽ trở thành giá trị trả về của chờ

Với kiến ​​thức này, và bởi vì tiện ích chờ mặc định bỏ qua các lỗi phần tử như vậy, chúng ta có thể cấu trúc lại các hướng dẫn của mình để ngắn gọn hơn

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
3

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
4

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
5

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
6

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
7

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
8

Trong ví dụ đó, chúng tôi chuyển vào một hàm ẩn danh (nhưng chúng tôi cũng có thể định nghĩa nó một cách rõ ràng như chúng tôi đã làm trước đó để nó có thể được sử dụng lại). Đối số đầu tiên và duy nhất được chuyển đến điều kiện của chúng tôi luôn là tham chiếu đến đối tượng trình điều khiển của chúng tôi, WebDriver. Trong môi trường đa luồng, bạn nên cẩn thận thao tác trên tham chiếu trình điều khiển được truyền vào điều kiện thay vì tham chiếu đến trình điều khiển ở phạm vi bên ngoài

Vì quá trình chờ sẽ không nuốt các lỗi phần tử như vậy được nêu ra khi không tìm thấy phần tử, nên điều kiện sẽ thử lại cho đến khi phần tử được tìm thấy. Sau đó, nó sẽ nhận giá trị trả về, một WebElement và chuyển nó trở lại tập lệnh của chúng ta

Nếu điều kiện thất bại, e. g. không bao giờ đạt được giá trị trả về trung thực từ điều kiện, thời gian chờ sẽ ném/tăng lỗi/ngoại lệ được gọi là lỗi hết thời gian chờ

Tùy chọn

Điều kiện chờ có thể được tùy chỉnh để phù hợp với nhu cầu của bạn. Đôi khi, không cần thiết phải chờ hết thời gian chờ mặc định, vì hình phạt nếu không đạt được điều kiện thành công có thể rất tốn kém

Sự chờ đợi cho phép bạn chuyển vào một đối số để ghi đè thời gian chờ

driver.get("file:///race_condition.html");
WebElement element = driver.findElement(By.tagName("p"));
assertEquals(element.getText(), "Hello from JavaScript!");
  
9

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
0

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
1

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
2

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
3

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
4

điều kiện dự kiến

Vì việc phải đồng bộ hóa DOM và hướng dẫn của bạn là điều khá phổ biến nên hầu hết các máy khách cũng đi kèm với một tập hợp các điều kiện dự kiến ​​được xác định trước. Như cái tên có thể rõ ràng, chúng là các điều kiện được xác định trước cho các hoạt động chờ đợi thường xuyên

Các điều kiện có sẵn trong các ràng buộc ngôn ngữ khác nhau sẽ khác nhau, nhưng đây là danh sách không đầy đủ của một số

  • cảnh báo có mặt
  • yếu tố tồn tại
  • phần tử có thể nhìn thấy
  • tiêu đề chứa
  • tiêu đề là
  • yếu tố ổn định
  • văn bản hiển thị

Bạn có thể tham khảo tài liệu API cho từng liên kết ứng dụng khách để tìm danh sách đầy đủ các điều kiện dự kiến

chờ đợi ngầm định

Có một loại chờ đợi thứ hai khác với gọi là chờ đợi ngầm định. Bằng cách chờ đợi ngầm định, WebDriver thăm dò DOM trong một khoảng thời gian nhất định khi cố gắng tìm bất kỳ phần tử nào. Điều này có thể hữu ích khi một số thành phần nhất định trên trang web không có sẵn ngay lập tức và cần một chút thời gian để tải

Theo mặc định, tính năng chờ ngầm cho các phần tử xuất hiện bị tắt và sẽ cần được bật theo cách thủ công trên cơ sở mỗi phiên. Trộn và đợi ẩn sẽ gây ra những hậu quả không lường trước được, cụ thể là đợi ngủ trong thời gian tối đa ngay cả khi phần tử có sẵn hoặc điều kiện là đúng

Cảnh báo. Không trộn lẫn chờ đợi ngầm và rõ ràng. Làm như vậy có thể gây ra thời gian chờ đợi không thể đoán trước. Ví dụ: đặt thời gian chờ ngầm định là 10 giây và thời gian chờ rõ ràng là 15 giây có thể khiến thời gian chờ xảy ra sau 20 giây

Chờ đợi ngầm định 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 cá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, nghĩa là bị vô hiệu hóa. Sau khi được đặt, thời gian chờ ngầm được đặt cho vòng đời của phiên

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
5

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
6

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
7

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
8

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"
  
9

driver.Navigate().GoToUrl("file:///race_condition.html");
IWebElement element = driver.FindElement(By.TagName("p"));
assertEquals(element.Text, "Hello from JavaScript!");
  
0

Lưu loátChờ đợi

Phiên bản FluentWait xác định lượng thời gian tối đa để chờ một điều kiện, cũng như tần suất kiểm tra điều kiện

Người dùng có thể định cấu hình chờ để bỏ qua các loại ngoại lệ cụ thể trong khi chờ, chẳng hạn như

require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
begin
  # Navigate to URL
  driver.get 'file:///race_condition.html'

  # Get and store Paragraph Text
  search_form = driver.find_element(:css,'p').text

  "Hello from JavaScript!".eql? search_form
ensure
  driver.quit
end
  
0 khi tìm kiếm một phần tử trên trang

Làm cách nào để đợi trang tải trong Selenium bằng JavaScript?

Trình điều khiển web Selenium. Đợi trang phức tạp có JavaScript tải .
chạy tập lệnh JavaScript dưới dạng WebDriver và lưu trữ kết quả của tài liệu. .
so sánh biến body với phiên bản trước của body. .
đợi một chút thời gian (ví dụ 50 ms)

Làm cách nào để đợi trang tải trong Selenium?

Chúng ta có thể đợi cho đến khi trang được tải hoàn toàn trong Selenium webdriver bằng cách sử dụng JavaScript Executor. Selenium có thể chạy các lệnh JavaScript với sự trợ giúp của phương thức execScript. Chúng tôi phải vượt qua tài liệu trở lại

Selenium có tải JavaScript không?

Trình quản trị web Selenium có thể thực thi Javascript . Sau khi tải một trang, bạn có thể thực thi bất kỳ javascript nào bạn muốn. Selenium phải được cài đặt webdriver để hoạt động. Tất cả những gì cần thiết để thực thi Javascript là gọi phương thức exec_script(js) trong đó js là mã javascript của bạn.

Chờ đợi tốt nhất để sử dụng trong Selenium là gì?

Cách tốt nhất để đợi thay đổi trong Selenium là sử dụng khái niệm đồng bộ hóa . Các chờ đợi ngầm định và rõ ràng có thể được sử dụng để xử lý chờ đợi. Tiềm ẩn là chờ đợi toàn cầu được áp dụng cho mọi phần tử trên trang. Giá trị mặc định của chờ ngầm định là 0.