2013-08-27 48 views
5

Tôi đang sử dụng Capybara 2.1 với Ruby 1.9.3 bằng trình điều khiển selen (với Minitest và Test Unit) để kiểm tra ứng dụng web.Lỗi StaleElementReference Không tìm thấy phần tử trong bộ nhớ cache

Tôi đang gặp khó khăn với sự cố StaleElementReferenceException. Tôi đã thấy khá nhiều cuộc thảo luận về chủ đề này nhưng tôi đã không thể tìm ra giải pháp cho vấn đề mà tôi đang gặp phải.

Vì vậy, về cơ bản, tôi đang cố gắng để tìm thấy tất cả các yếu tố pagination trên trang của mình sử dụng mã này:

pagination_elements = page.all('.pagination a') 

Sau đó, tôi đang làm một số khẳng định trên những yếu tố như:

pagination_elements.first.must_have_content('1') 

Sau những xác nhận đó, tôi tiếp tục thử nghiệm bằng cách nhấp vào liên kết Trang tiếp theo để đảm bảo rằng phần tử phân trang đầu tiên trong tương lai của tôi sẽ là Trang trước. Để làm điều đó tôi lấy paginations yếu tố nữa:

new_pagination_elements = page.all('.pagination a') 

Và Lỗi thiu đang xảy ra ở đây, bởi vì tôi đang đạt yếu tố mà tôi đã đạt được. (Here is the error)

Bạn có thể xem trạng thái liên kết here.

Tôi thực sự không có ý tưởng làm cách nào để thử nghiệm này hoạt động bình thường. Bạn có bất kỳ mẹo nào để có cách tiếp cận tốt hơn các yếu tố phân trang của tôi không?

+0

Hãy nhìn vào https://github.com/jnicklas/capybara/issues/843 –

+0

@RajarshiDas Tôi đã đọc chủ đề này và những người có liên quan, nhưng đó là một vấn đề thực sự cũ, từ một phiên bản trước của Capybara, và nó không giúp gì cho vấn đề của tôi. – Evers

Trả lời

1

tôi thấy thông điệp chính trong các ý chính là:

Element not found in the cache - 
perhaps the page has changed since it was looked up 

Tôi có trường hợp tương tự trước đó. Có hai giải pháp:

  1. Thêm page.reload trước khi kiểm tra cùng một nội dung trong trang mới, nếu bạn đã thiết lập Capybara.automatic_reload = false trong spec_helper

  2. find một yếu tố đặc biệt trong trang mới mà trang trước không có. Hiệu ứng này tương đương với chờ đợi.

Phương pháp khác là sử dụng bộ chọn cụ thể. Ví dụ, thay vì

pagination_elements = page.all('.pagination a') 

Sử dụng

pagination_elements = page.all('#post_123 .pagination a') 

Nối một khu vực id duy nhất để chọn và bạn không nên gặp vấn đề như vậy.

+0

Tôi rất muốn tránh sử dụng page.reload vì các bài kiểm tra tích hợp của tôi đang theo dõi luồng của người dùng và việc tải lại trang không phải là một phần của nó. – Evers

+0

@Evers, không có gì sai ở đây. Cài đặt mặc định là 'true', vì vậy mọi hành động sẽ tải lại nội dung, bạn chỉ không nhận thấy nó. Tôi luôn đặt nó là 'false' vì tôi sử dụng Javascript để tương tác thường xuyên. Quên phần này nếu bạn không có thiết lập như vậy trong 'spec_helper' –

+0

Nhưng một lực để' tải lại' có thể giúp nếu bạn kiểm tra cùng một thứ hai lần. Đang để thử. –

3

đôi khi tôi có một số vấn đề với AJAX trang chuyên sâu, trong trường hợp của tôi workaround này giải quyết nó:

begin 
    ... 
rescue Selenium::WebDriver::Error::StaleElementReferenceError 
    sleep 1 
    retry 
end 
0

có bạn cố gắng sử dụng WebDriver trực tiếp chứ không phải qua Capybara? Woudl này có khả năng cung cấp cho bạn nhiều quyền kiểm soát hơn khi nào và khi nào không cache đối tượng.

ví dụ:(Xin lỗi về cú pháp java nhưng nên lấy ý tưởng)

WebElement searchField = driver.findElement(By.CssSelector("input.foo")); 

searchField.click(); 

searchField.sendKeys("foo foo"); 

System.out.println(searchField.getText()); 

//Do something elsewhere on the page which causes html to change (e.g. submit form) 

..... 
.... 

//This next line would throw stale object 

System.out.println(searchField.getText()); 

//This line will not throw exception 

searchField = driver.findElement(By.CssSelector("input.foo")); 

System.out.println(searchField.getText()); 

Chỉ định "findElement" một lần nữa để "searchField" có nghĩa là chúng tôi tìm lại phần tử đó. Biết khi nào và khi nào không chuyển nhượng lại là chìa khóa đã quyết định cách cache các webelements của bạn.

Tôi chưa sử dụng Capybara, nhưng tôi cho rằng nó ẩn chiến lược lưu trong bộ nhớ cache của bạn?

+1

Chúng tôi đã sử dụng Capybara trên các dự án khác của chúng tôi và chúng tôi không xem xét để quay trở lại Webdriver chính nó. Capybara cứu chúng ta rất nhiều thời gian. Nhưng bạn là đúng, capybara có chiến lược bộ nhớ đệm, trong rất nhiều người khác :) – Evers

+0

Tôi sắp chuyển sang Ruby và đang cố gắng quyết định sử dụng thư viện nào. Đó là những thứ như thế này mà làm cho nghĩ rằng tôi sẽ chỉ sử dụng Webdriver trực tiếp. Tôi muốn kiểm soát quá nhiều để sử dụng một cái gì đó như Capybara –

+0

Downvote? Bit hà khắc –

1

Rõ ràng, ngoài điều kiện chủng tộc, lỗi này cũng xuất hiện do lạm dụng within khối. Ví dụ:

within '.edit_form' do 
    click '.edit_button' 
    # The error will appear here if the 'edit_button' is not a 
    # descendant of the 'edit_form' 
end 
+1

đó là trường hợp của tôi! Tôi đã bị khóa bên trong một khối "bên trong" đã gây ra một lỗi giả trên vật thể cũ bên trong nó - những gì đã được cũ không phải là những gì tôi đã 'tìm thấy', nhưng thay vì khối chính nó! – igorsantos07