CupCode.cc
Section 03 · Module 05 · Lesson 01 · ~15-20 นาที

การหา Elements ด้วย Locators

เวลาเรียน: 15-20 นาที ต้องรู้มาก่อน: Module 04 รูปแบบ: อ่าน + แบบฝึกสั้น ๆ

จบบทนี้แล้วคุณจะ...

  • อธิบายได้ว่า locator คืออะไร และทำไมมันถึงสำคัญต่อ automation
  • แยกแยะ locator ประเภทต่าง ๆ ได้ (ID, CSS, XPath, text, role)
  • ตัดสินได้ว่า locator ไหน "แข็งแรง" และ locator ไหน "เปราะบาง"
  • เข้าใจแนวคิด semantic locator และ data-testid
1 · Locator คืออะไร?

ลองนึกภาพคุณเป็นหุ่นยนต์ที่ถูกสั่งให้ "กดปุ่มสมัครสมาชิก" บนหน้าเว็บ คุณต้องมีวิธีบอกหุ่นยนต์ว่าปุ่มนั้นอยู่ตรงไหน — นั่นคือสิ่งที่ locator ทำ

Locator คือ "ที่อยู่" หรือ "คำอธิบาย" ที่ใช้ระบุตัวตนของ element บนหน้าเว็บ เพื่อให้เครื่องมือ automation หาเจอและทำงานกับมันได้

ถ้าเทียบกับชีวิตจริง:

  • ที่อยู่บ้าน = locator แบบ ID (เฉพาะเจาะจง ไม่ซ้ำใคร)
  • "บ้านสีแดงหลังที่สาม" = locator แบบ CSS (อธิบายลักษณะ)
  • "บ้านที่อยู่ถัดจากร้านกาแฟ ข้างซ้ายมือ ชั้นสอง" = locator แบบ XPath (อธิบายตำแหน่งเชิงโครงสร้าง)
2 · ประเภทของ Locators

ID Locator

หา element จาก attribute id ซึ่งควรจะไม่ซ้ำกันในหน้าเดียว

<button id="submit-btn">สมัคร</button>
  • ข้อดี: เร็ว, เฉพาะเจาะจง, ไม่เปลี่ยนบ่อย
  • ข้อเสีย: ไม่ใช่ทุก element จะมี id, บางระบบ generate id แบบ random

CSS Selector

ใช้ syntax เดียวกับ CSS ในการระบุ element

button.primary          → ปุ่มที่มี class "primary"
#login-form input[type="email"]  → input email ใน form login
.cart-item:first-child  → item แรกในตะกร้า
  • ข้อดี: ยืดหยุ่น, อ่านง่ายกว่า XPath, ทำงานเร็ว
  • ข้อเสีย: ไม่สามารถ traverse ขึ้น parent ได้

XPath

ใช้ path expression เพื่อนำทางใน DOM tree

//button[@id="submit-btn"]           → หาปุ่มจาก id
//div[@class="product"]//span[@class="price"]  → หาราคาในกล่องสินค้า
//input[preceding-sibling::label[text()="Email"]]  → input ที่อยู่หลัง label "Email"
  • ข้อดี: ทรงพลังมาก, traverse ได้ทุกทิศทาง
  • ข้อเสีย: อ่านยาก, ช้ากว่า CSS, เปราะบางถ้าเขียนไม่ดี

Text-based Locator

หา element จากข้อความที่แสดงบนหน้าจอ

"สมัครสมาชิก"   → หาปุ่มหรือ link ที่มีข้อความนี้
"เข้าสู่ระบบ"    → หาปุ่ม login
  • ข้อดี: ตรงกับสิ่งที่ผู้ใช้เห็น, อ่านง่ายมาก
  • ข้อเสีย: เปลี่ยนตามภาษา, พังถ้ามีการแก้ UI text

Role-based Locator (Semantic)

หา element จาก ARIA role หรือ semantic HTML

role="button" name="Submit"
role="textbox" name="Email"
role="navigation"
  • ข้อดี: สอดคล้องกับ accessibility, ไม่ผูกกับ implementation detail
  • ข้อเสีย: ต้องการ HTML ที่เขียนอย่าง semantic
3 · Locator ที่ดี vs Locator ที่เปราะบาง

ตัวอย่าง HTML

<div class="sc-kAzzGY bQRBFl">
  <div class="sc-bdnxRM jWxYRR">
    <form>
      <div class="form-group">
        <label>อีเมล</label>
        <input type="email" class="sc-gsnTZi kZNMAq" />
      </div>
      <button class="sc-dkzDqf gNPFYR btn-primary" data-testid="login-submit">
        เข้าสู่ระบบ
      </button>
    </form>
  </div>
</div>

Locator ที่เปราะบาง (AVOID)

Locator ปัญหา
.sc-kAzzGY.bQRBFl > .sc-bdnxRM > form > button class name จาก CSS-in-JS เปลี่ยนทุก build
/html/body/div[3]/div[1]/form/button absolute XPath พังทันทีเมื่อ layout เปลี่ยน
button.sc-dkzDqf.gNPFYR class name ที่ generate มาไม่มีความหมาย

Locator ที่แข็งแรง (PREFER)

Locator เหตุผล
[data-testid="login-submit"] สร้างมาเพื่อ testing โดยเฉพาะ, ไม่เปลี่ยนตาม UI
button:has-text("เข้าสู่ระบบ") ตรงกับสิ่งที่ผู้ใช้เห็น
role=button[name="เข้าสู่ระบบ"] semantic, accessibility-friendly
input[type="email"] ใช้ attribute ที่มี semantic meaning
4 · ทำไมถึงมี data-testid

data-testid คือ custom HTML attribute ที่ทีม dev เพิ่มเข้าไปเพื่อให้ automation หา element ได้ง่าย

<button data-testid="checkout-btn" class="sc-xyz abc123">
  ชำระเงิน
</button>

ทำไมต้องมี?

  • Class name อาจเปลี่ยนเมื่อ refactor CSS
  • Text อาจเปลี่ยนเมื่อแก้ UI copy
  • ID อาจไม่มีหรือถูกใช้เพื่อจุดประสงค์อื่น
  • data-testid ถูกสร้างมาเพื่อ testing โดยเฉพาะ ไม่มีผลต่อ styling หรือ functionality

ข้อตกลงในทีม: dev และ QA ควรตกลงกันว่าจะใส่ data-testid ที่ element สำคัญ ๆ ตั้งแต่ตอนเขียน code ไม่ใช่มาเพิ่มทีหลัง

5 · หลักการเลือก Locator

ลำดับความสำคัญในการเลือก locator (จากดีที่สุดไปน้อยที่สุด):

  1. Role/Semantic — role=button[name="Submit"]
  2. data-testid — [data-testid="submit-btn"]
  3. Text content — text="Submit"
  4. CSS Selector (stable attributes) — input[type="email"]
  5. ID — #submit-btn (ถ้ามั่นใจว่า stable)
  6. XPath (relative) — //form//button[@type="submit"]
  7. CSS (class-based) — .btn-primary (ถ้า class มีความหมาย)
  8. Absolute XPath — หลีกเลี่ยงให้ได้มากที่สุด
แบบฝึก: เลือก Locator Strategy ที่ดีที่สุด

โจทย์

ให้ HTML snippet ต่อไปนี้ แล้วเลือก locator ที่ดีที่สุดสำหรับแต่ละ element ที่ระบุ พร้อมอธิบายเหตุผล

<nav class="sc-abc123 main-nav">
  <ul>
    <li><a href="/home" class="nav-link active">หน้าหลัก</a></li>
    <li><a href="/products" class="nav-link">สินค้า</a></li>
    <li><a href="/cart" class="nav-link" data-testid="cart-link">
      ตะกร้า <span class="badge">3</span>
    </a></li>
  </ul>
</nav>

<main>
  <section class="sc-def456">
    <h2>สินค้าแนะนำ</h2>
    <div class="product-grid">
      <div class="sc-ghi789 product-card" data-testid="product-1">
        <img src="phone.jpg" alt="สมาร์ทโฟน XYZ" />
        <h3>สมาร์ทโฟน XYZ</h3>
        <span class="price" data-testid="price-1">฿12,900</span>
        <button class="sc-jkl012 add-to-cart" aria-label="เพิ่มสมาร์ทโฟน XYZ ลงตะกร้า">
          เพิ่มลงตะกร้า
        </button>
      </div>
    </div>
  </section>
</main>

คำถาม:

  1. หา link ไปหน้าตะกร้า
  2. หาราคาสินค้าชิ้นแรก
  3. หาปุ่ม "เพิ่มลงตะกร้า"
  4. หารูปสินค้า
  5. หา navigation ทั้ง block
ดูคำตอบแนะนำ
  1. Link ตะกร้า: [data-testid="cart-link"] — มี data-testid ให้แล้ว เป็น locator ที่ stable ที่สุด ไม่ต้องพึ่ง class name ที่อาจเปลี่ยน

  2. ราคาสินค้า: [data-testid="price-1"] — มี data-testid ให้แล้ว ดีกว่าใช้ .price เพราะถ้ามีสินค้าหลายชิ้น class จะซ้ำกัน

  3. ปุ่มเพิ่มลงตะกร้า: role=button[name="เพิ่มสมาร์ทโฟน XYZ ลงตะกร้า"] — ใช้ aria-label ที่เป็น semantic locator ดีกว่า class name ที่ generate มา หรือจะใช้ [data-testid="product-1"] button ก็ได้

  4. รูปสินค้า: img[alt="สมาร์ทโฟน XYZ"] — ใช้ alt text ซึ่งเป็น semantic attribute ดีกว่า src ที่อาจเปลี่ยน

  5. Navigation block: role=navigation หรือ nav — ใช้ semantic HTML tag ดีกว่า class name ที่ generate มา

สิ่งที่ต้องเอาติดตัวไปจากบทนี้

  • Locator คือวิธีที่ automation ใช้หา element บนหน้าเว็บ — เลือกดีหรือเลือกแย่ต่างกันลิบลับ
  • Locator ที่เปราะบาง (generated class, absolute XPath) จะทำให้ test พังบ่อยโดยไม่มีบั๊กจริง
  • Locator ที่แข็งแรง ใช้ semantic attributes, data-testid, หรือ role-based — ทนต่อการเปลี่ยนแปลง UI
  • data-testid เป็นข้อตกลงระหว่าง dev กับ QA ที่ช่วยให้ automation มั่นคง
  • การเลือก locator ที่ดีคือ ทักษะพื้นฐานที่สำคัญที่สุด ของ automation engineer