Web automation เขียน Xpath ยังไงให้ไม่เปราะ

oz4899
doppiotech
Published in
3 min readMar 2, 2022

สวัสดีครับ ช่วงหลังๆ มาอาจจะไม่ค่อยมีเวลาอัดวิดีโอ สอนเพิ่มเติมเท่าไหร่ใน youtube channel แต่ก็ยังอยากแชร์แบ่งปันประสบการณ์และเทคนิคต่างๆ ให้เพื่อนๆ พี่ๆ น้องๆ หลายๆคนได้มาคุยกัน วันนี้อยากจะมาพูดเรื่อง Xpath ครับ, ก่อนอื่นบอกก่อนว่า การ follow ตามบทความนี้ อาจจะต้องอาศัยพื้นความรู้การทำ Automation มาสักระดับนึงก่อน ถ้าใครยังเป็นมือใหม่ม๊าก แนะนำให้ลองไปดูคอร์ส Web automation ใน youtube channel ของ Doppio Tech ก่อน จะได้ follow ตามได้สนุกยิ่งขึ้นนะครับ

ทำไมต้องพูดเรื่อง Xpath

ก่อนอื่นเลยหลายๆ คนที่ทำ Web automation หรือแม้แต่ mobile app automation น่าจะคุ้นเคยกับเจ้า Xpath เป็นอย่างดี เพราะแม้ว่าบางทีเราจะรู้อยู่แล้วว่า การทำ automation ที่ดี ควรจะต้องมี locator อย่าง element id สิ จะทำให้ ​automation ของเรา Stable ที่สุด execute ได้ไวที่สุด และ cost ในการ maintain ต่ำที่สุด แต่ก็อย่างว่าครับว่า บางทีชีวิตจริงก็ไม่ได้โรยด้วยกลีบกุหลาบเสมอไป เรามักจะเจอปัจจัยแวดล้อมหลากหลายอย่างมาทำให้เราไม่ได้เจ้า element id นั้นมาครอบครองอย่างที่ฝัน เหตุผล classic ที่เจอจนหลายคนอาจจะพยักหน้าตาม ก็ได้แก่

  1. Dev ไม่มีเวลาจ้า ต้องทำ feature แค่งาน sprint ก็ขอบตาดำแล้ว
  2. Dev อยากทำแต่ไม่มีใครสนับสนุน อาจจะเพราะยังไม่ได้อยาก invest ใน automation test มากเพียงพอ เอาเวลา Dev ไปทำ new feature ดีกว่า

ซึ่งมันก็ทำให้เราต้องใช้ Xpath ในการทำ Automation อย่างหลีกเลี่ยงไม่ได้ เพราะฉะนั้นในบทความนี้เราจะไม่พูดถึงว่า จะแก้ปัญหาสองข้อด้านบนยังไง แต่เราจะมาพูดกันว่า ถ้าเราต้องใช้ Xpath จริงๆ เราทำยังไงให้มันดีที่สุดเท่าที่เราจะทำได้

Xpath มันมีปัญหายังไง ?

จริงๆ Xpath เป็น locator ที่มีความ flexible สูงมาก เรียกได้ว่าในแง่ของความยืดหยุ่น มันคือ King of locator เลยก็ว่าได้ แต่ทีนี้ปัญหาที่มักจะเกิดขึ้นคือ พอเราไม่ได้ระวัง หรือ มีเทคนิคในการใช้มันเพียงพอ มันเลยทำให้เกิดอาการที่เรียกว่า “เปราะ” ขึ้น (ผมคิดเอง เรียกเอง 55+) แล้วเราจะรู้ได้ไงว่า Xpath ที่เราเขียนอยู่มันมีอาการนี้หรือเปล่า ผมแนะนำให้สังเกตุ ง่ายๆ นะครับ

  1. อาการมันมักจะมาในเวลาที่มี release ใหม่ของ Application / Web
  2. อาการมันมักจะมาเวลาที่ต้องมีการเปลี่ยน test data
  3. อาการมันมักจะมาเวลาที่ต้องเอาขึ้นไปรันบน CI/CD

อาการที่ว่าก็คือ Script พังครับ (และจะตามมาด้วยประโยค Classic ว่า เฮ้ย แต่รันบนเครื่องผมยังผ่านอยู่เลย , และก็จะมีประโยคคำตอบ Classic ที่ตอบว่า แต่เราไม่ได้จะเอาเครื่องแกไปให้ทีม sprint test รัน เราใช้ CI/CD)

ต้นตอของปัญหามันคืออะไร

ปัญหาในการเขียน Xpath จริงๆ มันแบ่งได้เป็นแค่สองรูปแบบหลักๆ เท่านั้นเองครับคือ

  1. XPath คุณมันกว้างเกินไป
  2. Xpath คุณมันแคบเกินไป

ยกตัวอย่างง่ายๆ เช่น สมมติว่าเรากำลังทำงานอยู่บนหน้าเว็บที่ต้องกรอก OTP แล้วเราต้องการกรอกข้อมูลลงไปในช่อง โดยเราใช้ Xpath ว่า “//input” แน่นอนว่ามันใช้งานได้ แต่สิ่งที่เกิดขึ้นคือ ถ้าวันดีคืนดีหน้าจอนี้ มีการเพิ่ม กล่อง Input เข้ามาอีกกล่องนึง เราก็ไม่รู้หรอกว่ามันจะใช้งานได้ไหม มันอาจจะไปโดนกล่อง Input ใหม่ ที่ไม่ใช่กล่องสำหรับใส่เลข OTP แล้วก็เป็นได้ แบบนี้เราเรียกว่า การเขียน Xpath แบบ “กว้างเกินไป”

แล้วถ้า Xpath แบบแคบเกินไปล่ะ มันเป็นยังไง ตัวอย่างแบบ Classic สำหรับ Xpath แบบแคบเกินไป หาได้ไม่ยากครับ เปิด Chrome ขึ้นมา คลิ๊กขวาเลือก Inspect แล้ว คลิ๊กขวาที่ Html element ที่ต้องการแล้วเลือก “Copy Xpath” อันนี้หลายคนอาจจะอ้าปากแล้วตะโกนถามว่า “อ้าว!!! ไม่ได้หรอพี่” (ซึ่งพี่ก็จะตะโกนกลับไปว่า เออ !! ไม่ได้)
ถามว่า ทำไมไม่ได้ ลองดูตัวอย่าง Xpath ที่ได้จากการใช้วิธีด้านบนครับ
/html/div[1]/div[3]/span[2]/input[3]

ถ้าแปลเป็นภาษาเข้าใจง่ายคือแบบนี้ครับ

“จากข้างบนสุดนะ หา html ให้เจอจากนั้น ลงไปอีก 1 ขั้น (ห้ามมากกว่า) ให้เข้าไปใน div ตัวที่ 1 (ห้ามเป็นตัวอื่น) จากนั้นให้ไปหา div ตัวที่ 3 (ห้ามเป็นตัวอื่น) และจะเจอ Span ตัวที่ 2 จากนั้นก็จะเอา input ตัวที่ 3 มาใช้นะ”

คือจะเห็นว่า พอดูคำแปลแล้วจะรู้ว่า มันคือการ Fix ยิ่งกว่า Fix ใช่ไหมครับ คือหน้าเว็บห้ามมีการขยับเลยแม้แต่นิดเดียว ห้ามมีใครมาแทรก div เพิ่ม , แทรก span เพิ่มเด็ดขาด เพราะ ถ้าแกมาแทรก div เพิ่ม div ที่ชั้นต้องการอาจจะไม่ใช่ตัวที่ 1 แล้ว แต่กลายไปเป็นตัวที่ 2 แล้วautomate ชั้นก็จะพัง อันนี้แหละครับ ที่เค้าเรียกว่า การเขียน Xpath แบบ “แคบเกินไป”

ทริคและเทคนิคเล็กน้อยในการเขียน Xpath

  1. หลีกเลี่ยงการใช้อะไรที่คุณไม่เข้าใจใน Xpath
    ผมยกตัวอย่างง่ายๆ สำหรับโค้ด HTML ด้านล่างนะครับ
ตัวอย่างที่ 1 คำแปลกหน้าใน Xpath

สมมติว่าเราต้องการ div ใน html นี้โดยใช้ Xpath น้องหลายคนจะเขียนแบบนี้ครับ

//div[@class=’promotion-banner 3p-lg-x2’]

มันใช้งานได้ครับ แต่สิ่งที่มันไม่ดีคือ เราไม่ได้เข้าใจความหมายของไอ้คำว่า 3p-lg-x2 เลย (คำว่า promotion-banner ดูเป็นคำที่เข้าใจได้) แต่ 3p-lg-x2 นี่เราไม่รู้ว่ามันคืออะไรและมันจะเปลี่ยนเมื่อไหร่ เช่น

  • มันอาจจะเปลี่ยนเมื่อไปรันบนขนาดหน้าจอที่เปลี่ยนไปก็ได้
    (ผล: ไปรันเครื่องอื่นแล้วตาย)
  • มันอาจจะเปลี่ยนถ้ามีการเปลี่ยนสีหน้าเว็บไซต์ก็ได้
    (ผล: Dev แก้อะไรนิดนึงก็ตาย)
  • มันอาจจะเปลี่ยนถ้ามีการ resize ขนาด div ตัวนี้นิดนึงก็ได้
    (ผล: Dev แก้อะไรนิดนึงก็ตาย)

และยังมีเหตุผลอื่นๆ อีก เพราะฉะนั้นคำแนะนำแรกของผมคือ เวลาเขียน Xpath พยายามหลีกเลี่ยงสิ่งที่คุณไม่รู้จัก ถ้าเป็นผมจะเขียนประมาณว่า

//div[contains(@class,’promotion-banner’)]

2. ระวังการใช้ “*”
ผมเคยเจอน้องหลายคนที่นิยมเขียน Xpath ด้วยการใช้ “*” เช่น แทนที่จะเขียนว่า

//input[@placeholder=’Username’]

ก็มักจะเขียนเป็น

//*[@placeholder=’Username’]

บางทีก็เจอกับ Code reviewer บางคนที่เคยร่วมงานด้วย ที่ให้คนเปิด PR กลับไปแก้ว่าให้ใช้เป็นแบบ “*” แทน สำหรับตัวผมไม่ค่อยสนับสนุนการใช้ “*” มากนักโดยเฉพาะอย่างยิ่งตัวอย่างที่เขียนอยู่ข้างบน ลองคิดดูนะครับว่า ถ้าในอนาคตมันอาจจะมีอะไรสักอย่างนึงเพิ่มเข้ามาในหน้าเว็บ (ซึ่งไม่ใช่ input element) แล้วเราใช้ “*” นั่นหมายความว่า Xpath ของเราอาจจะไปจับโดนสิ่งใหม่สิ่งนั้นแทนที่จะเป็นสิ่งที่เราต้องการ ทำให้เกิดปัญหา Xpath กว้างเกินไป แต่ !! ก็มีบางกรณีนะครับที่ผมคิดว่าเห็นด้วยว่าควรจะมีการใช้ “*” นั่นคือ ถ้า Criteria ที่เราใช้ในการระบุ Xpath เป็นลักษณะของ id หรือ name ที่เราค่อนข้างมั่นใจว่ามันจะไม่มีอะไรมาซ้ำ ยกตัวอย่างเช่น

//div[@id='promotion-banner']/input[@placeholder='coupon']

ถ้าเป็นในลักษณะนี้แล้วจะเขียนเป็น

//*[@id='promotion-banner']/input[@placeholder='coupon']

อันนี้ผมว่าก็ไม่ได้เป็น Xpath ที่มีปัญหาเพราะเราค่อนข้างมั่นใจว่า บนหน้าเว็บคงไม่มี element ตัวอื่นที่จะถูกใส่เข้ามา แล้วมีคุณสมบัติ id=promotion-banner รวมทั้งนอกจากนี้การใช้ “*” ในกรณีนี้ยังช่วยให้เวลา Dev มีการแก้จาก div กลายไปเป็น element อื่น Xpath เราก็ยังมีความยืดหยุ่นพอที่จะไม่พังด้วย

3.อย่าใช้ Xpath ที่มันยาวเกินความจำเป็น

บางคนอาจจะเป็นคนขี้กลัว เวลาเขียน Xpath คือกลัวว่ามันจะออกมาแล้วมันไม่ Unique (ความหมายคือ Xpath ดันสามารถไปโดน element ได้มากกว่า 1 ตัว) ก็เลยชอบ play safe เน้นใส่ยาวไว้ก่อน เช่น

//div[@class='banner']/span[@class='subsection']//input[@data-identifier='promotion-code-input']

เวลาเจอกรณีแบบนี้ผมมักจะถามว่า ไอ้ div กับ span ข้างหน้าเนี้ย มันจำเป็นแค่ไหน ถ้าเว็บทั้งหน้านั้นมันดูแล้วน่าจะมีโอกาสมีกล่องให้ input promotion-code ได้แค่จุดเดียว และตัว data-identifier มันก็ดูจะเป็น criteria ที่ค่อนข้างโอเคในการนำไปถึงตัวนั้นแล้ว เราก็ไม่จำเป็นต้องเอาชีวิตเราไปฝากไว้กับ เจ้า div และ span ด้านหน้าให้วุ่นวาย เวลา Dev มีการแก้ มีการเปลี่ยนอะไรจะได้พอมี flexibility

จริงๆ ทริคเล็กทริคน้อยในการเขียน Xpath ยังมีอีกเยอะแยะ แต่วันนี้ขอแชร์ไว้เท่านี้ก่อนละกันครับ เดี๋ยวบทความนี้จะยาวเกินไป จนคนหลับซะก่อนจะอ่านมาถึงตรงนี้ และสำหรับการเขียน Xpath ผมว่ามันก็เป็นลักษณะการเขียนของแต่ละคนที่ adapt มาจากประสบการณ์ อาจจะมีเพื่อนๆ พี่ๆ บางคนที่อาจจะเขียนอีกแบบ ก็อยากให้มาแชร์ประสบการณ์กันนะครับ และสุดท้ายอยากฝากไว้ครับว่า “มี id ใช้ id, มี name ใช้ name ถ้าไม่มีจริงๆ ค่อยมา Xpath”

สุดท้ายจริงๆ ถ้าใครสนใจอยากหางานด้าน Automation test engineer แต่ไม่มีประสบการณ์ อยากหาบริษัทที่ยินดีโค้ช ยินดีสอน และแนะนำตั้งแต่เริ่มไปจนทำได้และเป็น expert ลองติดต่อเข้ามาได้นะครับ เรายังรับอีกหลายตำแหน่ง email หาเราได้ที่ careers@doppiotech.com สำหรับวันนี้ขอลาไปก่อน สวัสดีค้าบบ

--

--