Sự khác biệt giữa cssSelector & Xpath và cái nào tốt hơn về hiệu suất để kiểm tra trình duyệt chéo?


89

Tôi đang làm việc với Selenium WebDriver 2.25.0 trên ứng dụng web đa ngôn ngữ và chủ yếu kiểm tra nội dung trang (Đối với các ngôn ngữ khác nhau như tiếng Ả Rập, tiếng Anh, tiếng Nga, v.v.).

Đối với ứng dụng của tôi tốt hơn theo hiệu suất và đảm bảo rằng nó phải được hỗ trợ cho tất cả các trình duyệt (tức là IE 7,8,9, FF, Chrome, v.v.).

Cảm ơn trước cho những đề xuất có giá trị của bạn.

Câu trả lời:


108

Các bộ chọn CSS hoạt động tốt hơn nhiều so với Xpath và nó được ghi lại trong cộng đồng Selenium. Đây là một số lý do,

  • Các công cụ Xpath khác nhau trong mỗi trình duyệt, do đó làm cho chúng không nhất quán
  • IE không có công cụ xpath gốc, do đó selen sẽ đưa công cụ xpath của riêng mình vào để tương thích với API của nó. Do đó, chúng tôi đánh mất lợi thế của việc sử dụng các tính năng của trình duyệt gốc mà WebDriver vốn đã quảng bá.
  • Xpath có xu hướng trở nên phức tạp và do đó khó đọc theo ý kiến ​​của tôi

Tuy nhiên, có một số tình huống trong đó, bạn cần sử dụng xpath, ví dụ: tìm kiếm phần tử mẹ hoặc tìm kiếm phần tử theo văn bản của nó (tôi sẽ không khuyên dùng phần tử sau).

Bạn có thể đọc blog của Simon tại đây . Anh ấy cũng đề xuất CSS thay vì Xpath.

Nếu bạn đang kiểm tra nội dung thì không sử dụng các bộ chọn phụ thuộc vào nội dung của các phần tử. Đó sẽ là một cơn ác mộng bảo trì cho mọi ngôn ngữ. Hãy thử nói chuyện với các nhà phát triển và sử dụng các kỹ thuật mà họ đã sử dụng để ngoại hóa văn bản trong ứng dụng, như từ điển hoặc gói tài nguyên, v.v. Đây là blog của tôi giải thích chi tiết về điều đó.

chỉnh sửa 1

Cảm ơn @parishodak, đây là liên kết cung cấp các con số chứng minh rằng hiệu suất CSS tốt hơn


7
Bộ chọn CSS không cho phép văn bản. 'chứa' không được dùng trong CSS. Giống như tôi đã nói ở trên, có các bộ chọn độc lập với nội dung. Nội dung có thể cư trú bên ngoài. Bạn có thể nói chuyện với các nhà phát triển. Họ phải đã ngoại hóa văn bản. Hầu hết họ đều có từ điển cho mỗi ngôn ngữ. Vì vậy, các khóa trong từ điển giống nhau nhưng giá trị thay đổi theo ngôn ngữ. Bạn có thể sử dụng các tệp này để xác thực nội dung. Lưu ý rằng bạn cần chuyển đổi các ký tự gốc thành các ký tự ascii bằng cách sử dụng công cụ nativ2ascii từ JDK. Tôi phải viết một blog về điều này. Tôi đã kiểm tra nhiều ngôn ngữ bằng cách sử dụng kỹ thuật này.
nilesh

1
@Chetan चेतन Tôi đã thêm liên kết blog của mình trong câu trả lời. Xin lỗi đã mất một lúc. Hy vọng rằng điều đó sẽ giúp ích cho bạn.
nilesh

8
@Nilesh: Tôi không đồng ý với câu trả lời của bạn. 1.) Các công cụ CSS cũng khác nhau trong mỗi trình duyệt. Đây không phải là một cuộc tranh cãi. 3.) Với một số kinh nghiệm, XPath rất dễ hiểu và cung cấp nhiều chức năng hơn CSS. Nếu bạn tìm kiếm một phần tử rất lồng nhau thì chúng đều phức tạp: XPath và CSS. Theo kinh nghiệm của tôi, bất kỳ câu trả lời chung nào cho câu hỏi này sẽ sai. Quyết định CSS / XPATH phải được thực hiện riêng lẻ. Câu hỏi ban đầu là về hiệu suất. Câu trả lời của bạn chủ yếu bao gồm các giả định và ý kiến ​​cá nhân. Một minh chứng thực tế sẽ là ĐO LƯỜNG hiệu suất và đăng kết quả ở đây.
Elmue

2
Một bài viết rất hay mâu thuẫn với câu đầu tiên của bạn: "Bộ chọn CSS hoạt động tốt hơn nhiều so với Xpath". Nó không hề đơn giản, thậm chí có thể ngược lại. Và: "IE không có công cụ xpath gốc, do đó selen sẽ đưa công cụ xpath của riêng mình vào để tương thích với API của nó." Ở đây Selenium bị một lỗi thiết kế. Chắc chắn sẽ tốt hơn nếu triển khai công cụ XPath trong C ++ thay vì tập lệnh java. Nhưng IE đã chết, giờ có Edge. Đằng sau tất cả các câu hỏi về hiệu suất, người ta không được quên rằng CSS thiếu chức năng rất quan trọng như tìm kiếm văn bản của một phần tử.
Elmue

2
elementalselenium.com/tips/32-xpath-vs-css cung cấp các điểm chuẩn cho thấy css3 không còn nhanh hơn đáng kể.
mc0e

46

Tôi sẽ giữ quan điểm không phổ biến về thẻ SO selen rằng XPath sẽ thích hợp hơn CSS về lâu dài.

Bài đăng dài này có hai phần - đầu tiên tôi sẽ đưa ra bằng chứng xác thực về hiệu suất giữa hai phần là 0,1-0,3 mili giây (vâng, đó là 100 micro giây) và sau đó tôi sẽ chia sẻ ý kiến ​​của mình tại sao XPath mạnh hơn.


Hiệu suất khác biệt

Đầu tiên hãy giải quyết "con voi trong phòng" - xpath đó chậm hơn css.

Với sức mạnh cpu hiện tại (đọc: bất cứ thứ gì x86 được sản xuất từ ​​năm 2013) , ngay cả trên máy ảo browserstack / saucelabs / aws và sự phát triển của các trình duyệt (đọc: tất cả các trình duyệt phổ biến trong 5 năm qua) , điều đó hầu như không xảy ra. Các công cụ của trình duyệt đã phát triển, sự hỗ trợ của xpath là đồng nhất, IE không phải là hình ảnh (hy vọng với hầu hết chúng ta) . So sánh này trong câu trả lời khác đang được trích dẫn khắp nơi, nhưng nó rất phù hợp với ngữ cảnh - có bao nhiêu người đang chạy - hoặc quan tâm đến - tự động hóa chống lại IE8?

Nếu có sự khác biệt, nó nằm trong một phần của mili giây .

Tuy nhiên, hầu hết các khung công tác cấp cao hơn đều thêm ít nhất 1ms chi phí trên lệnh gọi selen thô (trình bao bọc, trình xử lý, lưu trữ trạng thái, v.v.); vũ khí cá nhân của tôi lựa chọn - RobotFramework - thêm ít nhất 2ms, mà tôi rất vui khi hy sinh cho những gì nó cung cấp. Một vòng mạng từ AWS us-East-1 đến trung tâm của BrowserStack thường là 11 mili giây .

Vì vậy, với các trình duyệt từ xa nếu có sự khác biệt giữa xpath và css, nó sẽ bị lu mờ bởi mọi thứ khác, theo thứ tự độ lớn.


Sự đo, sự đo lường

Không có nhiều so sánh công khai (tôi thực sự chỉ thấy một câu được trích dẫn) , vì vậy - đây là một trường hợp đơn giản, giả và đơn giản.
Nó sẽ xác định vị trí của một phần tử theo hai chiến lược X lần và so sánh thời gian trung bình cho phần tử đó.

Mục tiêu - trang đích của BrowserStack và nút "Đăng ký" của nó; ảnh chụp màn hình html khi viết bài này:

nhập mô tả hình ảnh ở đây

Đây là mã thử nghiệm (python):

from selenium import webdriver
import timeit


if __name__ == '__main__':

    xpath_locator = '//div[@class="button-section col-xs-12 row"]'
    css_locator = 'div.button-section.col-xs-12.row'

    repetitions = 1000

    driver = webdriver.Chrome()
    driver.get('https://www.browserstack.com/')

    css_time = timeit.timeit("driver.find_element_by_css_selector(css_locator)", 
                             number=repetitions, globals=globals())
    xpath_time = timeit.timeit('driver.find_element_by_xpath(xpath_locator)', 
                             number=repetitions, globals=globals())

    driver.quit()

    print("css total time {} repeats: {:.2f}s, per find: {:.2f}ms".
          format(repetitions, css_time, (css_time/repetitions)*1000))
    print("xpath total time for {} repeats: {:.2f}s, per find: {:.2f}ms".
          format(repetitions, xpath_time, (xpath_time/repetitions)*1000))

Đối với những người không quen thuộc với Python - nó sẽ mở trang và tìm phần tử - trước tiên bằng bộ định vị css, sau đó với xpath; thao tác tìm được lặp lại 1.000 lần. Đầu ra là tổng thời gian tính bằng giây cho 1.000 lần lặp lại và thời gian trung bình cho một lần tìm thấy tính bằng mili giây.

Bộ định vị là:

  • for xpath - "một phần tử div có giá trị lớp chính xác này, ở đâu đó trong DOM";
  • css cũng tương tự - "một phần tử div với lớp này, ở đâu đó trong DOM".

Được chọn có chủ ý để không bị điều chỉnh quá mức; ngoài ra, bộ chọn lớp được trích dẫn cho css là "nhanh thứ hai sau một id".

Môi trường - Chrome v66.0.3359.139, chromedriver v2.38, cpu: ULV Core M-5Y10 thường chạy ở tốc độ 1,5GHz (vâng, một "xử lý văn bản", thậm chí không phải là một con thú i7 thông thường) .

Đây là kết quả:

css total time 1000 repeats: 8.84s, per find: 8.84ms

xpath total time for 1000 repeats: 8.52s, per find: 8.52ms

Rõ ràng là thời gian cho mỗi lần tìm thấy khá gần nhau; sự khác biệt là 0,32 mili giây . Đừng nhảy "đường dẫn xpath nhanh hơn" - đôi khi đúng như vậy, đôi khi là css.


Hãy thử với một bộ định vị khác, phức tạp hơn một chút - một thuộc tính có chuỗi con (ít nhất là cách tiếp cận phổ biến đối với tôi, đi sau lớp của phần tử khi một phần của nó mang ý nghĩa chức năng) :

xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'

Hai bộ định vị lại giống nhau về mặt ngữ nghĩa - "tìm một phần tử div có trong thuộc tính lớp của nó là chuỗi con này".
Đây là kết quả:

css total time 1000 repeats: 8.60s, per find: 8.60ms

xpath total time for 1000 repeats: 8.75s, per find: 8.75ms

Diff của 0.15ms .


Là một bài tập - bài kiểm tra tương tự như được thực hiện trong blog được liên kết trong phần nhận xét / câu trả lời khác - trang kiểm tra là công khai và mã kiểm tra cũng vậy .

Họ đang thực hiện một số việc trong mã - nhấp vào một cột để sắp xếp theo nó, sau đó nhận các giá trị và kiểm tra việc sắp xếp giao diện người dùng có đúng không.
Tôi sẽ cắt nó - chỉ cần lấy bộ định vị, sau cùng - đây là kiểm tra gốc, phải không?

Mã tương tự như trên, với những thay đổi sau trong:

  • Url bây giờ là http://the-internet.herokuapp.com/tables; có 2 bài kiểm tra.

  • Bộ định vị cho cái đầu tiên - "Tìm phần tử theo ID và lớp" - là:

css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"

Và đây là kết quả:

css total time 1000 repeats: 8.24s, per find: 8.24ms

xpath total time for 1000 repeats: 8.45s, per find: 8.45ms

Chênh lệch 0,2 mili giây.

"Tìm các yếu tố bằng cách đi ngang":

css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"

Kết quả:

css total time 1000 repeats: 9.29s, per find: 9.29ms

xpath total time for 1000 repeats: 8.79s, per find: 8.79ms

Lần này là 0,5 ms (ngược lại, xpath hóa ra "nhanh hơn" ở đây).

Vì vậy, 5 năm sau (các công cụ trình duyệt tốt hơn) chỉ tập trung vào hiệu suất của bộ định vị (không có các hành động như sắp xếp trong giao diện người dùng, v.v.), cùng một thử nghiệm - thực tế không có sự khác biệt giữa CSS và XPath.


Vì vậy, ngoài xpath và css, bạn nên chọn cái nào trong hai cái để đạt hiệu suất? Câu trả lời rất đơn giản - chọn định vị theo id .

Tóm lại, nếu id của một phần tử là duy nhất (vì nó được cho là theo các thông số kỹ thuật), thì giá trị của nó đóng một vai trò quan trọng trong biểu diễn nội bộ của trình duyệt đối với DOM và do đó thường là nhanh nhất.

Tuy nhiên, id duy nhất và không đổi (ví dụ không phải được tạo tự động) không phải lúc nào cũng có sẵn, điều này đưa chúng ta đến "tại sao XPath nếu có CSS?"


Ưu điểm của XPath

Với hiệu suất ngoài bức tranh, tại sao tôi nghĩ xpath tốt hơn? Đơn giản - linh hoạt và mạnh mẽ.

Xpath là một ngôn ngữ được phát triển để làm việc với các tài liệu XML; như vậy, nó cho phép các cấu trúc mạnh mẽ hơn nhiều so với css.
Ví dụ: điều hướng theo mọi hướng trong cây - tìm một phần tử, sau đó đi đến ông bà của nó và tìm kiếm phần tử con của nó có các thuộc tính nhất định.
Nó cho phép các điều kiện boolean được nhúng - cond1 and not(cond2 or not(cond3 and cond4)); bộ chọn nhúng - "tìm một div có các con với các thuộc tính này, sau đó điều hướng theo nó".
XPath cho phép tìm kiếm dựa trên giá trị của một nút (văn bản của nó) - tuy nhiên, thực tế này rất hữu ích, nó có ích, đặc biệt là trong các tài liệu có cấu trúc không tốt (không có thuộc tính xác định để bước vào, như id động và lớp - định vị phần tử bằng văn bản của nó nội dung) .

Bước trong css chắc chắn dễ dàng hơn - người ta có thể bắt đầu viết các bộ chọn chỉ trong vài phút; nhưng sau một vài ngày sử dụng, sức mạnh và khả năng xpath đã nhanh chóng vượt qua css.
Và hoàn toàn chủ quan - một css phức tạp khó đọc hơn nhiều so với một biểu thức xpath phức tạp.

Outro;)

Cuối cùng, một lần nữa rất chủ quan - nên chọn cái nào?

IMO, không có sự lựa chọn đúng hay sai - chúng là những giải pháp khác nhau cho cùng một vấn đề và nên chọn cái nào phù hợp hơn với công việc.

Là "fan" của XPath, tôi không ngại sử dụng kết hợp cả hai trong các dự án của mình - heck, đôi khi chỉ cần ném CSS một cái sẽ nhanh hơn nhiều, nếu tôi biết nó sẽ hoạt động tốt.


Có bao nhiêu nút có trang đăng nhập? Các trang đăng nhập thường rất đơn giản vì vậy đó là lý do tại sao bạn có thể thấy sự khác biệt nhỏ.
pagep

Các bài kiểm tra hiệu suất khác cho thấy sự khác biệt lớn hơn nhiều trên các trình duyệt khác nhau.
pagep

1
Đối với câu hỏi đầu tiên của bạn - ảnh chụp màn hình DOM có trong câu trả lời và trang này trực tuyến và công khai. Đối với đầu tiên và thứ hai của bạn, nếu bạn đọc kỹ câu trả lời, tôi đã lặp lại bài kiểm tra tương tự với elementalselenium, một trong số ít các so sánh có sẵn thường được trích dẫn, sử dụng cùng một mục tiêu và trình định vị như chúng, nhưng chỉ với các trình duyệt mới hơn 5 năm. .
Todor Minakov

3
@TodorMinakov BÀI ĐĂNG TUYỆT VỜI !!! Tôi đồng ý với bạn 100% Tôi cũng nghĩ rằng cú pháp XPath cũng tự nhiên hơn (ít nhất là đối với tôi) vì nó giống với thứ mà chúng ta đều biết rất rõ. Và đó là đường dẫn tệp / thư mục. Vì vậy, tôi nghĩ một người không có kiến ​​thức về CSS hoặc XPath, sẽ học XPath dễ dàng hơn nhiều. Vì sự khác biệt về hiệu suất là không đáng kể, tôi nghĩ rằng đường cong học tập đáng được cân nhắc.
hfontanez

1
Cảm ơn bạn @hfontanez; Tôi chưa nghĩ đến cấu trúc hệ thống tệp tương tự tuyệt vời. Tuy nhiên, tôi phải không đồng ý một chút cho sự dễ dàng của bước vào - ban đầu, cú pháp XPath có thể hơi đáng sợ, cộng với nó có một số gotcha-s ( ví dụ []sau chỉ mục //) . Nhưng sau ngày đầu tiên học và sử dụng nó, hầu hết mọi người đều vượt qua điểm giới hạn của đường cong học tập :) (css bước vào dễ dàng hơn, IMHO) .
Todor Minakov

13

Cuộc tranh luận giữa cssSelectorXPath sẽ vẫn là một trong những cuộc tranh luận chủ quan nhất trong Cộng đồng Selenium . Những gì chúng ta đã biết cho đến nay có thể được tóm tắt là:

  • Những người ủng hộ cssSelector nói rằng nó dễ đọc hơn và nhanh hơn (đặc biệt là khi chạy trên Internet Explorer).
  • Trong khi những người ủng hộ XPath nói rằng nó có khả năng chuyển trang (trong khi cssSelector không thể).
  • Duyệt qua DOM trong các trình duyệt cũ hơn như IE8 không hoạt động với cssSelector nhưng tốt với XPath .
  • XPath có thể đi lên DOM (ví dụ: từ con đến cha), trong khi cssSelector chỉ có thể đi xuống DOM (ví dụ: từ cha sang con)
  • Tuy nhiên, việc không thể duyệt qua DOM bằng cssSelector trong các trình duyệt cũ hơn không hẳn là một điều xấu vì nó là một dấu hiệu cho thấy trang của bạn có thiết kế kém và có thể được hưởng lợi từ một số đánh dấu hữu ích.
  • Ben Burton đề cập rằng bạn nên sử dụng cssSelector vì đó là cách các ứng dụng được xây dựng. Điều này làm cho các bài kiểm tra dễ dàng hơn để viết, nói về và nhờ những người khác giúp duy trì.
  • Adam Goucher nói rằng hãy áp dụng một cách tiếp cận kết hợp hơn - trước tiên tập trung vào ID, sau đó là cssSelector và chỉ tận dụng XPath khi bạn cần (ví dụ: đi bộ lên DOM) và XPath sẽ luôn mạnh hơn đối với các bộ định vị nâng cao.

Dave Haeffner đã thực hiện một bài kiểm tra trên một trang có hai bảng dữ liệu HTML , một bảng được viết mà không có các thuộc tính hữu ích ( IDClass ) và bảng còn lại có chúng. Tôi đã phân tích chi tiết quy trình thử nghiệm và kết quả của thử nghiệm này trong phần thảo luận Tại sao tôi nên sử dụng bộ chọn cssSelector thay vì XPath để kiểm tra tự động? . Mặc dù thử nghiệm này đã chứng minh rằng mỗi Chiến lược định vị là tương đương hợp lý trên các trình duyệt, nhưng nó không vẽ nên bức tranh toàn cảnh cho chúng tôi. Dave Haeffner trong cuộc thảo luận khác Css Vs. Đường dẫn X, Dưới kính hiển viđã đề cập, trong một thử nghiệm từ đầu đến cuối, có rất nhiều biến số khác khi khởi động Sauce chơi , khởi động Trình duyệtđộ trễ đến và đi từ ứng dụng đang thử nghiệm. Điều đáng tiếc rút ra từ thử nghiệm đó có thể là một trình điều khiển có thể nhanh hơn trình điều khiển kia (ví dụ: IE vs Firefox ), trong khi thực tế thì không phải vậy. Để có được cảm nhận thực sự về sự khác biệt hiệu suất giữa cssSelectorXPath, chúng tôi cần tìm hiểu sâu hơn. Chúng tôi đã làm điều đó bằng cách chạy mọi thứ từ một máy cục bộ trong khi sử dụng tiện ích đo điểm chuẩn hiệu suất. Chúng tôi cũng tập trung vào một hành động Selenium cụ thể hơn là toàn bộ quá trình chạy thử nghiệm và chạy nhiều lần. Tôi đã phân tích quy trình thử nghiệm cụ thể và kết quả của thử nghiệm này chi tiết trong cuộc thảo luận cssSelector vs XPath cho selen . Nhưng các thử nghiệm vẫn thiếu một khía cạnh tức là phạm vi trình duyệt nhiều hơn (ví dụ: Internet Explorer 9 và 10) và thử nghiệm trên một trang lớn hơn và sâu hơn.

Dave Haeffner trong một cuộc thảo luận khác Css Vs. X Path, Dưới kính hiển vi (Phần 2) đề cập, để đảm bảo các điểm chuẩn bắt buộc được bao phủ theo cách tốt nhất có thể, chúng ta cần xem xét một ví dụ minh họa một trang lớn và sâu .


Test SetUp

Để chứng minh ví dụ chi tiết này, một máy ảo Windows XP đã được thiết lập và Ruby (1.9.3) đã được cài đặt. Tất cả các trình duyệt có sẵn và trình điều khiển trình duyệt tương đương của chúng cho Selenium cũng đã được cài đặt. Để đo điểm chuẩn, lib tiêu chuẩn của Ruby benchmarkđã được sử dụng.


Mã kiểm tra

require_relative 'base'
require 'benchmark'

class LargeDOM < Base

  LOCATORS = {
    nested_sibling_traversal: {
      css: "div#siblings > div:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3)",
      xpath: "//div[@id='siblings']/div[1]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]"
    },
    nested_sibling_traversal_by_class: {
      css: "div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1",
      xpath: "//div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]"
    },
    table_header_id_and_class: {
      css: "table#large-table thead .column-50",
      xpath: "//table[@id='large-table']//thead//*[@class='column-50']"
    },
    table_header_id_class_and_direct_desc: {
      css: "table#large-table > thead .column-50",
      xpath: "//table[@id='large-table']/thead//*[@class='column-50']"
    },
    table_header_traversing: {
      css: "table#large-table thead tr th:nth-of-type(50)",
      xpath: "//table[@id='large-table']//thead//tr//th[50]"
    },
    table_header_traversing_and_direct_desc: {
      css: "table#large-table > thead > tr > th:nth-of-type(50)",
      xpath: "//table[@id='large-table']/thead/tr/th[50]"
    },
    table_cell_id_and_class: {
      css: "table#large-table tbody .column-50",
      xpath: "//table[@id='large-table']//tbody//*[@class='column-50']"
    },
    table_cell_id_class_and_direct_desc: {
      css: "table#large-table > tbody .column-50",
      xpath: "//table[@id='large-table']/tbody//*[@class='column-50']"
    },
    table_cell_traversing: {
      css: "table#large-table tbody tr td:nth-of-type(50)",
      xpath: "//table[@id='large-table']//tbody//tr//td[50]"
    },
    table_cell_traversing_and_direct_desc: {
      css: "table#large-table > tbody > tr > td:nth-of-type(50)",
      xpath: "//table[@id='large-table']/tbody/tr/td[50]"
    }
  }

  attr_reader :driver

  def initialize(driver)
    @driver = driver
    visit '/large'
    is_displayed?(id: 'siblings')
    super
  end

  # The benchmarking approach was borrowed from
  # http://rubylearning.com/blog/2013/06/19/how-do-i-benchmark-ruby-code/
  def benchmark
    Benchmark.bmbm(27) do |bm|
      LOCATORS.each do |example, data|
    data.each do |strategy, locator|
      bm.report(example.to_s + " using " + strategy.to_s) do
        begin
          ENV['iterations'].to_i.times do |count|
         find(strategy => locator)
          end
        rescue Selenium::WebDriver::Error::NoSuchElementError => error
          puts "( 0.0 )"
        end
      end
    end
      end
    end
  end

end

Các kết quả

LƯU Ý : Đầu ra tính bằng giây và kết quả là tổng thời gian chạy của 100 lần thực thi.

Trong Biểu mẫu:

css_xpath_under_microscopev2

Ở dạng biểu đồ:

  • Chrome :

chart-chrome

  • Firefox :

biểu đồ-firefox

  • Internet Explorer 8 :

chart-ie8

  • Internet Explorer 9 :

chart-ie9

  • Internet Explorer 10 :

chart-ie10

  • Opera :

biểu đồ-opera


Phân tích kết quả

  • Chrome và Firefox được điều chỉnh rõ ràng để có hiệu suất cssSelector nhanh hơn .
  • Internet Explorer 8 là một gói cssSelector sẽ không hoạt động, quá trình duyệt XPath mất kiểm soát mất ~ 65 giây và quá trình duyệt bảng 38 giây mà không có kết quả cssSelector nào để so sánh với nó.
  • Trong IE 9 và 10, XPath nhìn chung nhanh hơn. Trong Safari, đó là một sự cố gắng, ngoại trừ một vài lần chạy duyệt chậm hơn với XPath . Và trên hầu hết tất cả các trình duyệt, việc truyền tải các ô trong bảngô bảng lồng nhau được thực hiện với XPath là một hoạt động tốn kém.
  • Điều này không có gì đáng ngạc nhiên vì các bộ định vị rất giòn và không hiệu quả và chúng ta cần phải tránh chúng.

Tóm lược

  • Nhìn chung, có hai trường hợp mà XPath chậm hơn rõ rệt so với cssSelector . Nhưng chúng có thể dễ dàng tránh được.
  • Sự khác biệt về hiệu suất hơi có lợi cho cho các trình duyệt không phải IE và hơi ủng hộ cho trình duyệt IE.

Chuyện bên lề

Bạn có thể tự mình thực hiện đánh dấu băng ghế dự bị bằng cách sử dụng thư viện này , nơi Dave Haeffner đã tổng hợp tất cả các mã.

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.