cssSelector & Xpath แตกต่างกันอย่างไรและข้อใดดีกว่าเมื่อเทียบกับประสิทธิภาพสำหรับการทดสอบข้ามเบราว์เซอร์


89

ฉันกำลังทำงานกับ Selenium WebDriver 2.25.0 บนเว็บแอปพลิเคชันหลายภาษาและทดสอบเนื้อหาของหน้าเป็นหลัก (สำหรับภาษาต่างๆเช่นอาหรับอังกฤษรัสเซียและอื่น ๆ )

สำหรับแอปพลิเคชันของฉันซึ่งดีกว่าตามประสิทธิภาพและตรวจสอบให้แน่ใจว่าควรรองรับเบราว์เซอร์ทั้งหมด (เช่น IE 7,8,9, FF, Chrome เป็นต้น)

ขอบคุณล่วงหน้าสำหรับคำแนะนำที่มีค่าของคุณ

คำตอบ:


109

ตัวเลือก CSS ทำงานได้ดีกว่า Xpath มากและได้รับการบันทึกไว้อย่างดีในชุมชน Selenium นี่คือเหตุผลบางประการ

  • เอ็นจิ้น Xpath แตกต่างกันไปในแต่ละเบราว์เซอร์จึงทำให้ไม่สอดคล้องกัน
  • IE ไม่มีเอ็นจิ้น xpath ดั้งเดิมดังนั้นซีลีเนียมจึงฉีดเอ็นจิ้น xpath ของตัวเองเพื่อความเข้ากันได้ของ API ดังนั้นเราจึงสูญเสียประโยชน์จากการใช้คุณสมบัติเบราว์เซอร์ดั้งเดิมที่ WebDriver ส่งเสริมโดยเนื้อแท้
  • Xpath มีแนวโน้มที่จะซับซ้อนและทำให้ยากต่อการอ่านในความคิดของฉัน

อย่างไรก็ตามมีบางสถานการณ์ที่คุณต้องใช้ xpath ตัวอย่างเช่นค้นหาองค์ประกอบหลักหรือองค์ประกอบการค้นหาด้วยข้อความ (ฉันจะไม่แนะนำในภายหลัง)

คุณสามารถอ่านบล็อกจากไซมอนที่นี่ นอกจากนี้เขายังแนะนำ CSS บน Xpath

หากคุณกำลังทดสอบเนื้อหาอย่าใช้ตัวเลือกที่ขึ้นอยู่กับเนื้อหาขององค์ประกอบ นั่นจะเป็นฝันร้ายในการซ่อมบำรุงสำหรับทุกพื้นที่ ลองพูดคุยกับนักพัฒนาและใช้เทคนิคที่พวกเขาใช้เพื่อทำให้ข้อความในแอปพลิเคชันอยู่ภายนอกเช่นพจนานุกรมหรือชุดทรัพยากรเป็นต้นนี่คือบล็อกของฉันที่อธิบายรายละเอียดไว้

แก้ไข 1

ขอบคุณ @parishodak นี่คือลิงค์ที่ให้ตัวเลขที่พิสูจน์ว่าประสิทธิภาพของ CSS ดีกว่า


7
ตัวเลือก CSS ไม่อนุญาตข้อความ "มี" เลิกใช้แล้วใน CSS อย่างที่ฉันได้กล่าวไว้ข้างต้นมีตัวเลือกที่เป็นอิสระจากเนื้อหา เนื้อหาสามารถอยู่ภายนอกได้ คุณสามารถพูดคุยกับนักพัฒนา พวกเขาจะต้องทำให้ข้อความอยู่ภายนอก พวกเขาส่วนใหญ่มีพจนานุกรมต่อสถานที่ ดังนั้นคีย์ในพจนานุกรมจึงเหมือนกัน แต่ค่าจะเปลี่ยนไปตามโลแคล คุณสามารถใช้ไฟล์เหล่านี้เพื่อตรวจสอบความถูกต้องของเนื้อหา โปรดทราบว่าคุณต้องแปลงอักขระเนทีฟเป็นอักขระ ascii โดยใช้เครื่องมือ nativ2ascii จาก JDK ฉันต้องเขียนบล็อกเกี่ยวกับเรื่องนี้ ฉันได้ทดสอบหลายภาษาโดยใช้เทคนิคนี้
nilesh

1
@Chetan चेतनฉันเพิ่มลิงค์บล็อกของฉันในคำตอบ ขออภัยที่ใช้เวลาสักครู่ หวังว่าจะช่วยคุณได้
nilesh

8
@Nilesh: ฉันไม่เห็นด้วยกับคำตอบของคุณ 1. ) เครื่องมือ CSS ยังแตกต่างกันในแต่ละเบราว์เซอร์ นี่ไม่ใช่ข้อโต้แย้ง 3. ) ด้วยประสบการณ์บางอย่าง XPath นั้นเข้าใจง่ายมากและมีฟังก์ชันมากกว่า CSS หากคุณค้นหาองค์ประกอบที่ซ้อนกันมากองค์ประกอบเหล่านี้จะซับซ้อนทั้ง XPath และ CSS จากประสบการณ์ของฉันคำตอบทั่วไปสำหรับคำถามนี้จะไม่ถูกต้อง CSS / XPATH การตัดสินใจต้องดำเนินการทีละรายการ คำถามเดิมคือเกี่ยวกับประสิทธิภาพ คำตอบของคุณส่วนใหญ่ประกอบด้วยสมมติฐานและความคิดเห็นส่วนตัว การพิสูจน์ที่แท้จริงคือการวัดประสิทธิภาพและโพสต์ผลลัพธ์ที่นี่
Elmue

2
บทความที่ดีมากซึ่งขัดแย้งกับประโยคแรกของคุณ: "ตัวเลือก CSS ทำงานได้ดีกว่า Xpath มาก" มันไม่ง่ายอย่างนั้นมันอาจจะตรงกันข้ามด้วยซ้ำ และ: "IE ไม่มีเอ็นจิ้น xpath ดั้งเดิมดังนั้นซีลีเนียมจะฉีดเอ็นจิ้น xpath ของตัวเองเพื่อความเข้ากันได้ของ API" ที่นี่ซีลีเนียมประสบข้อผิดพลาดในการออกแบบ มันจะเป็นการดีกว่าที่จะใช้เอ็นจิ้น XPath ใน C ++ แทนสคริปต์ java แต่ IE ตายแล้วตอนนี้ Edge มาแล้ว เบื้องหลังคำถามเกี่ยวกับประสิทธิภาพทั้งหมดอย่าลืมว่า CSS ขาดฟังก์ชันที่สำคัญมากเช่นการค้นหาข้อความขององค์ประกอบ
Elmue

2
elementalselenium.com/tips/32-xpath-vs-cssมีการวัดประสิทธิภาพที่แนะนำว่า css3 ไม่เร็วกว่าอย่างมีนัยสำคัญอีกต่อไป
mc0e

46

ฉันจะถือความเห็นที่ไม่เป็นที่นิยมในแท็ก SO ซีลีเนียมว่าXPath นั้นดีกว่า CSS ในระยะยาว

โพสต์แบบยาวนี้มีสองส่วนก่อนอื่นฉันจะใส่หลักฐานด้านหลังของผ้าเช็ดปากความแตกต่างของประสิทธิภาพระหว่างทั้งสองคือ0.1-0.3 มิลลิวินาที (ใช่นั่นคือ 100 ไมโครวินาที)แล้วฉันจะแบ่งปันความคิดเห็นของฉันว่าทำไม XPath มีประสิทธิภาพมากขึ้น


ความแตกต่างของประสิทธิภาพ

ก่อนอื่นเรามาจัดการกับ "ช้างในห้อง" - xpath นั้นช้ากว่า css

ด้วยพลังซีพียูปัจจุบัน(อ่าน: x86 ทุกอย่างที่ผลิตตั้งแต่ปี 2013)แม้กระทั่งบน browserstack / saucelabs / aws VMs และการพัฒนาเบราว์เซอร์(อ่าน: สิ่งที่เป็นที่นิยมทั้งหมดในช่วง 5 ปีที่ผ่านมา)ซึ่งแทบจะไม่เป็นเช่นนั้น เครื่องมือเบราว์เซอร์ได้มีการพัฒนา, การสนับสนุนของ XPath เป็นชุด, IE เป็นออกจากภาพ(หวังว่าสำหรับส่วนมากของเรา) การเปรียบเทียบนี้ในคำตอบอื่น ๆ กำลังถูกอ้างถึงทั่วทุกที่ แต่มันเป็นไปตามบริบท - มีกี่คนที่กำลังทำงานหรือสนใจ - ระบบอัตโนมัติกับ IE8?

หากมีความแตกต่างก็คือในส่วนของมิลลิวินาที

อย่างไรก็ตามเฟรมเวิร์กระดับสูงกว่าส่วนใหญ่จะเพิ่มค่าโสหุ้ยอย่างน้อย 1ms เหนือการเรียกซีลีเนียมดิบอย่างไรก็ตาม (wrapper, handlers, state storage etc) อาวุธประจำตัวที่ฉันเลือก - RobotFramework - เพิ่มอย่างน้อย 2ms ซึ่งฉันมีความสุขมากกว่าที่จะเสียสละเพื่อสิ่งที่ให้มา บินบนเครือข่ายจาก AWS เราตะวันออก-1 กับฮับ BrowserStack มักจะเป็น11 มิลลิวินาที

ดังนั้นด้วยเบราว์เซอร์ระยะไกลหากมีความแตกต่างระหว่าง xpath และ css มันจะถูกบดบังด้วยสิ่งอื่นใดตามลำดับขนาด


การวัด

มีการเปรียบเทียบสาธารณะไม่มากนัก(ฉันเคยเห็นเพียงตัวเดียวที่อ้างถึงเท่านั้น)ดังนั้นนี่คือกรณีตัวอย่างคร่าวๆแบบจำลองและแบบง่ายๆ
มันจะค้นหาองค์ประกอบตามสองกลยุทธ์ X ครั้งและเปรียบเทียบเวลาเฉลี่ยสำหรับสิ่งนั้น

เป้าหมาย - หน้า Landing Page ของ BrowserStack และปุ่ม "สมัคร" ภาพหน้าจอของ html ขณะเขียนโพสต์นี้:

ใส่คำอธิบายภาพที่นี่

นี่คือรหัสทดสอบ (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))

สำหรับผู้ที่ไม่คุ้นเคยกับ Python - จะเปิดหน้าและค้นหาองค์ประกอบ - อันดับแรกด้วย css locator จากนั้นใช้ xpath การดำเนินการค้นหาซ้ำ 1,000 ครั้ง ผลลัพธ์คือเวลารวมเป็นวินาทีสำหรับการทำซ้ำ 1,000 ครั้งและเวลาเฉลี่ยสำหรับหนึ่งครั้งที่พบในหน่วยมิลลิวินาที

ตัวระบุตำแหน่งคือ:

  • สำหรับ xpath - "องค์ประกอบ div ที่มีค่าคลาสที่แน่นอนนี้อยู่ที่ไหนสักแห่งใน DOM";
  • css นั้นคล้ายกัน - "องค์ประกอบ div กับคลาสนี้อยู่ที่ไหนสักแห่งใน DOM"

เลือกโดยเจตนาที่จะไม่ปรับแต่งมากเกินไป นอกจากนี้ตัวเลือกคลาสยังถูกอ้างถึงสำหรับ css ว่า "เร็วที่สุดเป็นอันดับสองรองจาก id"

สภาพแวดล้อม - Chrome v66.0.3359.139, chromedriver v2.38, CPU: ULV หลัก M-5Y10 มักจะทำงานที่ 1.5GHz (ใช่ "การประมวลผลคำ" หนึ่งไม่ได้ i7 สัตว์ปกติ)

นี่คือผลลัพธ์:

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

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

แน่นอนว่าการกำหนดเวลาต่อการค้นพบนั้นค่อนข้างใกล้เคียงกัน แตกต่างกันคือ0.32 มิลลิวินาที อย่ากระโดด "xpath เร็วกว่า" - บางครั้งก็เป็นบางครั้งก็เป็น css


ลองใช้ตัวระบุตำแหน่งอีกชุดหนึ่งซึ่งซับซ้อนกว่าเล็กน้อย - แอตทริบิวต์ที่มีสตริงย่อย(อย่างน้อยวิธีการทั่วไปสำหรับฉันจะตามหลังคลาสขององค์ประกอบเมื่อส่วนหนึ่งของมันมีความหมายเชิงการทำงาน) :

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

ตัวระบุตำแหน่งทั้งสองมีความหมายเหมือนกันอีกครั้ง - "ค้นหาองค์ประกอบ div ที่มีในคลาสแอตทริบิวต์สตริงย่อยนี้"
นี่คือผลลัพธ์:

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

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

Diff ของ0.15ms


ในฐานะที่เป็นแบบฝึกหัด - การทดสอบเดียวกันกับที่ทำในบล็อกที่เชื่อมโยงในความคิดเห็น / คำตอบอื่น ๆ - หน้าทดสอบเป็นแบบสาธารณะและรหัสทดสอบก็เช่นกัน

พวกเขากำลังทำสองสิ่งในโค้ด - คลิกที่คอลัมน์เพื่อจัดเรียงจากนั้นรับค่าและตรวจสอบการจัดเรียง UI ว่าถูกต้อง
ฉันจะตัดมัน - แค่หาตัวระบุตำแหน่ง - นี่คือการทดสอบรูทใช่ไหม

รหัสเดียวกับด้านบนโดยมีการเปลี่ยนแปลงเหล่านี้ใน:

  • URL คือตอนนี้http://the-internet.herokuapp.com/tables; มีการทดสอบ 2 ครั้ง

  • ตัวระบุตำแหน่งสำหรับรายการแรก - "การค้นหาองค์ประกอบตาม ID และคลาส" คือ:

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

และนี่คือผลลัพธ์:

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

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

ความแตกต่าง0.2มิลลิวินาที

"การค้นหาองค์ประกอบโดยการข้ามผ่าน":

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

ผลลัพธ์:

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

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

คราวนี้เป็น0.5มิลลิวินาที (ในทางกลับกัน xpath กลายเป็น "เร็วกว่า" ที่นี่)

5 ปีต่อมา (เอ็นจิ้นเบราว์เซอร์ที่ดีกว่า) และมุ่งเน้นไปที่ประสิทธิภาพของตัวระบุตำแหน่งเท่านั้น (ไม่มีการดำเนินการเช่นการเรียงลำดับใน UI ฯลฯ ) การทดสอบแบบเดียวกันไม่มีความแตกต่างระหว่าง CSS และ XPath ในทางปฏิบัติ


ดังนั้นจาก xpath และ css จะเลือกประสิทธิภาพแบบไหน คำตอบนั้นง่าย - เลือกตำแหน่งของคุณ id

เรื่องสั้นขนาดยาวหาก id ขององค์ประกอบไม่ซ้ำกัน (ตามที่ควรจะเป็นตามข้อกำหนด) ค่าของมันจะมีบทบาทสำคัญในการแสดง DOM ภายในของเบราว์เซอร์และโดยปกติจะเร็วที่สุด

อย่างไรก็ตามรหัสที่ไม่ซ้ำกันและคงที่(เช่นไม่ได้สร้างขึ้นโดยอัตโนมัติ)จะไม่สามารถใช้ได้เสมอไปซึ่งจะนำเราไปสู่ ​​"ทำไมต้องใช้ XPath ถ้ามี CSS"


ข้อได้เปรียบ XPath

ด้วยประสิทธิภาพที่ออกมาจากภาพทำไมฉันคิดว่า xpath ดีกว่า? ง่าย - เก่งกาจและทรงพลัง

Xpath เป็นภาษาที่พัฒนาขึ้นสำหรับการทำงานกับเอกสาร XML ดังนั้นจึงช่วยให้สามารถสร้างโครงสร้างที่มีประสิทธิภาพมากกว่า css
ตัวอย่างเช่นการนำทางในทุกทิศทางในต้นไม้ - ค้นหาองค์ประกอบจากนั้นไปที่ปู่ย่าตายายและค้นหาลูกของมันที่มีคุณสมบัติบางอย่าง
อนุญาตให้ฝังเงื่อนไขบูลีน - cond1 and not(cond2 or not(cond3 and cond4)); ตัวเลือกที่ฝังไว้ - "ค้นหา div ที่มีลูกเหล่านี้พร้อมคุณสมบัติเหล่านี้จากนั้นนำทางไปตามนั้น"
XPath ช่วยให้การค้นหาตามค่าของโหนด (ข้อความ) - อย่างไรก็ตามการปฏิบัติตามนี้มีประโยชน์ แต่ก็มีประโยชน์โดยเฉพาะอย่างยิ่งในเอกสารที่มีโครงสร้างไม่ดี(ไม่มีแอตทริบิวต์ที่แน่นอนที่ต้องดำเนินการเช่นรหัสและคลาสแบบไดนามิก - ค้นหาองค์ประกอบด้วยข้อความ เนื้อหา) .

การก้าวใน css นั้นง่ายกว่าอย่างแน่นอน - เราสามารถเริ่มเขียนตัวเลือกได้ในเวลาไม่กี่นาที แต่หลังจากใช้งานไปสองสามวันพลังและความเป็นไปได้ของ xpath ก็เอาชนะ css ได้อย่างรวดเร็ว
และเป็นอัตนัยล้วนๆ - css ที่ซับซ้อนอ่านยากกว่านิพจน์ xpath ที่ซับซ้อนมาก

เอาท์โร;)

สุดท้ายเป็นเรื่องส่วนตัวมากอีกครั้ง - จะเลือกอันไหนดี?

IMO ไม่มีทางเลือกที่ถูกหรือผิด - เป็นวิธีแก้ปัญหาที่แตกต่างกันสำหรับปัญหาเดียวกันและควรเลือกอะไรที่เหมาะสมกับงาน

การเป็น "แฟน" ของ XPath ฉันไม่อายที่จะใช้ทั้งสองอย่างในโปรเจ็กต์ของฉัน แต่บางครั้งการโยน CSS ก็เร็วกว่ามากถ้าฉันรู้ว่ามันจะทำงานได้ดี


หน้าล็อกอินมีกี่โหนด? หน้าเข้าสู่ระบบมักจะเรียบง่ายมากนั่นเป็นสาเหตุที่คุณอาจเห็นความแตกต่างเพียงเล็กน้อย
pagep

การทดสอบประสิทธิภาพอื่น ๆ แสดงให้เห็นความแตกต่างที่ใหญ่กว่ามากในเบราว์เซอร์ต่างๆ
pagep

1
สำหรับคำถามแรกของคุณภาพหน้าจอของ DOM จะปรากฏอยู่ในคำตอบและหน้านั้นออนไลน์และเป็นสาธารณะ สำหรับครั้งแรกและครั้งที่สองของคุณหากคุณอ่านคำตอบอย่างถี่ถ้วนฉันได้ทำการทดสอบซ้ำเช่นเดียวกับ elementalselenium ซึ่งเป็นหนึ่งในการเปรียบเทียบที่มีอยู่ไม่กี่ตัวที่มีการอ้างถึงบ่อยครั้งโดยใช้เป้าหมายและตัวระบุตำแหน่งเดียวกันกับเบราว์เซอร์รุ่นใหม่เพียง 5 ปี .
Todor Minakov

3
@TodorMinakov โพสต์ที่ดี !!! ฉันเห็นด้วยกับคุณ 100% ฉันยังคิดว่าไวยากรณ์ XPath นั้นเป็นธรรมชาติมากกว่า (อย่างน้อยสำหรับฉัน) เพราะมันคล้ายกับสิ่งที่เราทุกคนรู้จักเป็นอย่างดี และนั่นคือเส้นทางของไฟล์ / โฟลเดอร์ ดังนั้นฉันคิดว่าคนที่ไม่มีความรู้เรื่อง CSS หรือ XPath จะเรียนรู้ XPath ได้ง่ายกว่ามาก เนื่องจากความแตกต่างของประสิทธิภาพเป็นเรื่องเล็กน้อยฉันคิดว่าเส้นโค้งการเรียนรู้ควรพิจารณาอย่างดี
hfontanez

1
ขอบคุณ @hfontanez; การเปรียบเทียบที่ดีกับโครงสร้างระบบไฟล์ฉันไม่ได้คิด ฉันต้องไม่เห็นด้วยเล็กน้อยสำหรับขั้นตอนในความสะดวกสบายแม้ว่า - ไวยากรณ์ XPath สามารถเป็นบิตข่มขู่ในตอนแรกรวมทั้งจะมีบางส่วน gotcha-s (ดัชนี[]หลังจาก//ตัวอย่าง) แต่หลังจากวันเริ่มต้นของการเรียนรู้และการใช้มันทุกคนสวยมากข้ามจุดเปลี่ยนของเส้นโค้งการเรียนรู้ :) (ขั้นตอน CSS ในการเป็น admitably ง่ายขึ้น IMHO)
Todor Minakov

13

การอภิปรายระหว่างcssSelector VS XPathจะยังคงเป็นหนึ่งในการอภิปรายอัตนัยมากที่สุดในชุมชนซีลีเนียม สิ่งที่เรารู้อยู่แล้วสามารถสรุปได้ดังนี้:

  • ผู้ที่ชื่นชอบcssSelectorกล่าวว่าอ่านได้ง่ายขึ้นและเร็วขึ้น (โดยเฉพาะเมื่อทำงานกับ Internet Explorer)
  • ในขณะที่ผู้ที่ชื่นชอบXPathก็สามารถข้ามหน้าได้ (ในขณะที่cssSelectorไม่สามารถทำได้)
  • traversing DOM ในเบราว์เซอร์รุ่นเก่าเช่น IE8 ไม่ได้ทำงานกับcssSelectorแต่จะดีกับXPath
  • XPathสามารถเดินขึ้น DOM (เช่นจากเด็กไปยังผู้ปกครอง) ในขณะที่cssSelectorสามารถข้าม DOM ได้เท่านั้น (เช่นจากผู้ปกครองไปยังเด็ก)
  • อย่างไรก็ตามการไม่สามารถสำรวจ DOM ด้วยcssSelectorในเบราว์เซอร์รุ่นเก่าก็ไม่จำเป็นต้องเป็นเรื่องเลวร้ายเนื่องจากเป็นตัวบ่งชี้ว่าหน้าของคุณมีการออกแบบที่ไม่ดีและอาจได้รับประโยชน์จากมาร์กอัปที่เป็นประโยชน์
  • Ben Burtonกล่าวว่าคุณควรใช้cssSelectorเพราะนั่นคือวิธีสร้างแอปพลิเคชัน ทำให้ข้อสอบง่ายขึ้นเขียนพูดถึงและให้คนอื่นช่วยดูแล
  • Adam Goucherกล่าวว่าจะใช้แนวทางแบบผสมผสานมากขึ้นโดยเน้นที่ ID เป็นอันดับแรกจากนั้นจึงใช้cssSelectorและใช้ประโยชน์จากXPathเมื่อคุณต้องการเท่านั้น (เช่นการเดินขึ้น DOM) และXPathนั้นจะมีประสิทธิภาพมากขึ้นสำหรับตัวระบุตำแหน่งขั้นสูง

เดฟ Haeffnerดำเนินการทดสอบบนหน้าเว็บที่มีตารางข้อมูลสอง HTMLโต๊ะหนึ่งที่เขียนโดยไม่ต้องคุณลักษณะที่เป็นประโยชน์ ( IDและชั้น ) และอื่น ๆ กับพวกเขา ฉันได้วิเคราะห์ขั้นตอนการทดสอบและผลของการทดลองนี้โดยละเอียดแล้วในการอภิปรายเหตุใดฉันจึงควรใช้cssSelector selector ซึ่งต่างจาก XPath สำหรับการทดสอบอัตโนมัติ . แม้ว่าการทดลองนี้แสดงให้เห็นว่าแต่ละกลยุทธ์ของ Locatorมีความเท่าเทียมกันอย่างสมเหตุสมผลในเบราว์เซอร์ แต่ก็ไม่ได้วาดภาพรวมให้เราอย่างเพียงพอ Dave Haeffnerในการสนทนาอื่น ๆCss Vs. เส้นทาง X ภายใต้กล้องจุลทรรศน์กล่าวในการทดสอบแบบ end-to-end ที่มีอยู่เป็นจำนวนมากของตัวแปรอื่น ๆ ที่เล่นเริ่มต้นซอส , เบราว์เซอร์เริ่มต้นขึ้นและแฝงไปและกลับจากการประยุกต์ใช้ภายใต้การทดสอบ สิ่งที่น่าเสียดายที่เกิดขึ้นจากการทดลองนั้นอาจเป็นไปได้ว่าไดรเวอร์ตัวหนึ่งอาจเร็วกว่าอีกตัว (เช่นIEเทียบกับFirefox ) ซึ่งในความเป็นจริงนั้นไม่ได้เป็นเช่นนั้นเลย เพื่อให้ได้รสชาติที่แท้จริงของความแตกต่างของประสิทธิภาพระหว่างcssSelectorและXPathเราจำเป็นต้องเจาะลึกลงไป เราทำได้โดยการเรียกใช้ทุกอย่างจากเครื่องท้องถิ่นในขณะที่ใช้ยูทิลิตี้การเปรียบเทียบประสิทธิภาพ นอกจากนี้เรายังมุ่งเน้นไปที่การกระทำของซีลีเนียมที่เฉพาะเจาะจงมากกว่าการทดสอบทั้งหมดและดำเนินการหลาย ๆ ครั้ง ผมได้วิเคราะห์เฉพาะขั้นตอนการทดสอบและผลของการทดลองนี้ในรายละเอียดในการอภิปรายcssSelector VS XPath สำหรับซีลีเนียม แต่การทดสอบยังขาดไปอีกด้านหนึ่งนั่นคือความครอบคลุมของเบราว์เซอร์ที่มากขึ้น (เช่น Internet Explorer 9 และ 10) และการทดสอบกับหน้าที่มีขนาดใหญ่และลึกกว่า

Dave Haeffnerในการสนทนาอื่นCss Vs. X เส้นทางภายใต้กล้องจุลทรรศน์ (Part 2)กล่าวในการสั่งซื้อเพื่อให้แน่ใจว่ามาตรฐานที่จำเป็นต้องได้รับความคุ้มครองในทางที่ดีที่สุดที่เราต้องพิจารณาตัวอย่างที่แสดงให้เห็นหน้าขนาดใหญ่และลึก


ทดสอบการตั้งค่า

แสดงให้เห็นถึงรายละเอียดเช่นนี้ Windows XP เครื่องเสมือนเป็นการติดตั้งและทับทิม (1.9.3)ได้รับการติดตั้ง เบราว์เซอร์ที่มีอยู่ทั้งหมดและไดรเวอร์ของเบราว์เซอร์ที่เทียบเท่าสำหรับ Selenium ก็ได้รับการติดตั้งด้วย สำหรับการเปรียบเทียบbenchmarkจะใช้lib มาตรฐานของ Ruby


รหัสทดสอบ

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

ผล

หมายเหตุ : ผลลัพธ์เป็นหน่วยวินาทีและผลลัพธ์เป็นเวลาดำเนินการทั้งหมด 100 ครั้ง

ในรูปแบบตาราง:

css_xpath_under_microscopev2

ในรูปแบบแผนภูมิ:

  • Chrome :

แผนภูมิโครเมี่ยม

  • Firefox :

แผนภูมิ firefox

  • Internet Explorer 8 :

แผนภูมิ -E8

  • Internet Explorer 9 :

แผนภูมิ -E9

  • Internet Explorer 10 :

แผนภูมิ - ie10

  • โอเปร่า :

ชาร์ตโอเปร่า


การวิเคราะห์ผลลัพธ์

  • Chrome และ Firefox ได้รับการปรับแต่งอย่างชัดเจนเพื่อประสิทธิภาพcssSelector ที่เร็วขึ้น
  • Internet Explorer 8 เป็นถุงเก็บของcssSelectorที่ใช้งานไม่ได้การข้ามผ่านXPath ที่ไม่สามารถควบคุมได้ซึ่งใช้เวลาประมาณ 65 วินาทีและการข้ามตาราง 38 วินาทีโดยไม่มีผลลัพธ์cssSelectorเพื่อเปรียบเทียบ
  • ใน IE 9 และ 10 XPathจะเร็วกว่าโดยรวม ใน Safari ก็โยนขึ้นยกเว้นสำหรับคู่ของช้าลงสำรวจเส้นทางวิ่งด้วยXPath และในเกือบทุกเบราว์เซอร์การข้ามผ่านเซลล์แบบซ้อนกันและการส่งผ่านเซลล์ตารางที่ทำด้วยXPathเป็นการดำเนินการที่มีราคาแพง
  • สิ่งเหล่านี้ไม่น่าแปลกใจเนื่องจากตัวระบุตำแหน่งมีความเปราะและไม่มีประสิทธิภาพและเราจำเป็นต้องหลีกเลี่ยง

สรุป

  • โดยรวมมีสองกรณีที่XPathโดดเด่นช้ากว่าcssSelector แต่หลีกเลี่ยงได้ง่าย
  • ประสิทธิภาพแตกต่างกันเล็กน้อย สำหรับเบราว์เซอร์ที่ไม่ใช่ IE และเป็นที่นิยมเล็กน้อย สำหรับเบราว์เซอร์ IE

เรื่องไม่สำคัญ

คุณสามารถทำเครื่องหมายบัลลังก์ได้ด้วยตัวคุณเองโดยใช้ไลบรารีนี้ซึ่งDave Haeffnerรวบรวมรหัสทั้งหมดไว้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.