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

Assertions และ Waiting Strategies

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

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

  • อธิบายได้ว่า assertion คืออะไร และมันตรวจสอบอะไรบ้าง
  • แยกแยะ hard assertion vs soft assertion ได้
  • เข้าใจปัญหาของ timing ใน automation และทำไม sleep() ถึงเป็นทางเลือกที่แย่
  • รู้จัก explicit wait, implicit wait, และ polling strategy
  • ออกแบบ waiting strategy ที่เหมาะสมกับสถานการณ์ได้
1 · Assertion คืออะไร?

Assertion คือ "คำยืนยัน" ที่ test ใช้ตรวจสอบว่าผลลัพธ์ตรงตามที่คาดหวังหรือไม่

ถ้า test เป็นเหมือนการทดลองวิทยาศาสตร์:

  • ขั้นตอน = Action (คลิก, พิมพ์, navigate)
  • Assertion = การตรวจสอบผลลัพธ์ (เห็นข้อความที่ถูกต้อง, element แสดงผล, ค่าเปลี่ยนไป)

Test ที่ไม่มี assertion เหมือนการทดลองที่ไม่ได้วัดผล — ไม่มีประโยชน์

ตัวอย่าง Assertions (concept level)

สิ่งที่ตรวจสอบ ตัวอย่าง
Element visible หลังจาก login สำเร็จ, ชื่อผู้ใช้ต้องแสดงบนหน้าจอ
Text content ข้อความ "สั่งซื้อสำเร็จ" ต้องปรากฏใน confirmation page
Value ยอดรวมในตะกร้าต้องเป็น ฿12,900
Count จำนวนสินค้าในตะกร้าต้องเป็น 3 ชิ้น
State ปุ่ม "ยืนยัน" ต้อง disabled จนกว่าจะกรอกข้อมูลครบ
URL หลัง redirect ต้องอยู่ที่หน้า /dashboard
2 · Hard Assertion vs Soft Assertion

Hard Assertion

  • หยุดทันที เมื่อ assertion fail
  • Test case จบ ณ จุดนั้น ไม่ทำต่อ
  • เหมาะกับ: critical check ที่ถ้าไม่ผ่านแล้วทำต่อไปก็ไม่มีประโยชน์

ตัวอย่าง: test login → ถ้า login ไม่สำเร็จ ก็ไม่มีประโยชน์จะเช็คหน้า dashboard ต่อ

Soft Assertion

  • เก็บ failure ไว้ แล้วทำต่อจนจบ test case
  • รายงาน failure ทั้งหมดทีเดียวตอนท้าย
  • เหมาะกับ: validation หลายจุดในหน้าเดียว ที่อยากรู้ทุก failure พร้อมกัน

ตัวอย่าง: test หน้า profile → เช็คชื่อ, อีเมล, เบอร์โทร, ที่อยู่ — อยากรู้ว่าอะไรผิดบ้างทั้งหมด ไม่ใช่เจอชื่อผิดแล้วหยุดเลย

เมื่อไหร่ใช้อะไร?

สถานการณ์ ใช้
Login / authentication check Hard
การเช็ค prerequisite ก่อนทำ step ถัดไป Hard
Validation หลายช่องในฟอร์มเดียว Soft
เช็ค UI elements หลายตัวในหน้าเดียว Soft
3 · ปัญหา Timing ใน Automation

เรื่องเล่า: test ที่ใช้ sleep(5000) แล้วยังพัง

ทีม QA ของบริษัท e-commerce แห่งหนึ่งมี automation test ที่ทดสอบการค้นหาสินค้า ขั้นตอนคือ:

  1. พิมพ์คำค้นหา
  2. กดปุ่มค้นหา
  3. sleep(5000) — รอ 5 วินาที
  4. เช็คว่าผลลัพธ์แสดง

Test ผ่านบนเครื่อง dev ทุกครั้ง แต่พอรันบน CI server กลับ fail 30% ของเวลา

สาเหตุ: CI server ใช้ network ร่วมกับระบบอื่น บางครั้ง API response กลับมาใน 2 วินาที บางครั้ง 8 วินาที — sleep(5000) ไม่พอในบางรอบ

ทีมแก้โดยเพิ่มเป็น sleep(10000) — test ช้าลง แต่ก็ยังพังอยู่ดีเมื่อ network โหลดหนัก

ปัญหาที่แท้จริง: sleep() เป็นการ "เดาเวลา" — ถ้าเร็วกว่าที่เดาก็เสียเวลาเปล่า ถ้าช้ากว่าที่เดาก็ fail

4 · Waiting Strategies

Implicit Wait

  • กำหนด timeout กลาง เช่น "ทุก element รอได้สูงสุด 10 วินาที"
  • apply กับทุกการหา element โดยอัตโนมัติ
  • ข้อดี: ตั้งครั้งเดียวใช้ทั้ง project
  • ข้อเสีย: ไม่ยืดหยุ่น, อาจรอนานเกินจำเป็นสำหรับ element ที่ควรเจอเร็ว

Explicit Wait

  • กำหนด condition ที่ต้องรอ เช่น "รอจนกว่า element จะ visible"
  • กำหนด timeout เฉพาะจุด
  • ข้อดี: ยืดหยุ่น, รอเท่าที่จำเป็น, อ่านเข้าใจว่ารออะไร
  • ข้อเสีย: เขียน code มากขึ้น

Polling

  • ตรวจสอบ condition ซ้ำ ๆ ทุก X milliseconds จนกว่าจะสำเร็จหรือ timeout
  • เป็นกลไกภายในของ explicit wait
  • ตัวอย่าง: เช็คทุก 500ms ว่า loading spinner หายไปหรือยัง

ทำไม sleep() ถึงแย่

sleep() Explicit Wait
รอเท่าเดิมทุกครั้ง แม้ element พร้อมแล้ว รอเท่าที่จำเป็น
ถ้า element ช้ากว่าที่เดาก็ fail มี timeout ที่เหมาะสม
ทำให้ test suite ช้าลงมาก ทำให้ test suite เร็วที่สุดเท่าที่จะเป็นไปได้
อ่าน code แล้วไม่รู้ว่ารออะไร อ่าน code แล้วเข้าใจว่ารอ condition อะไร

Timeout Strategy

หลักการตั้ง timeout:

  • ค่า default: 10-30 วินาที (ขึ้นกับ application)
  • API calls: 15-30 วินาที
  • Page load: 30-60 วินาที
  • File upload/download: 60-120 วินาที
  • Never: ไม่ตั้ง timeout เลย (test อาจค้างไม่มีกำหนด)
5 · กลับมาแก้ปัญหา e-commerce

ทีมแก้ปัญหาโดยเปลี่ยนจาก sleep(5000) เป็น:

"รอจนกว่า loading spinner จะหายไป และผลลัพธ์การค้นหาจะแสดง (timeout 30 วินาที)"

ผลลัพธ์:

  • test ที่เคย fail 30% กลายเป็น fail 0%
  • test ทำงานเร็วขึ้นเฉลี่ย 3 วินาทีต่อเคส (เพราะไม่ต้องรอ 5 วินาทีเมื่อ response กลับเร็ว)
  • test suite 200 เคส ประหยัดเวลาได้ 10 นาทีต่อรอบ
แบบฝึก: วิเคราะห์ Test Code ที่มี Timing Issues

โจทย์

ดู test pseudocode ต่อไปนี้ แล้ววิเคราะห์ปัญหาและแนะนำวิธีแก้

Test: ทดสอบการเพิ่มสินค้าลงตะกร้า

1. เปิดหน้าสินค้า
2. sleep(3000)
3. คลิกปุ่ม "เพิ่มลงตะกร้า"
4. sleep(2000)
5. assert: badge ตะกร้าแสดงเลข "1"
6. คลิกปุ่ม "ไปหน้าตะกร้า"
7. sleep(5000)
8. assert: ชื่อสินค้าแสดงในตะกร้า
9. assert: ราคาสินค้าถูกต้อง
10. assert: ปุ่ม "ชำระเงิน" enabled

คำถาม:

  1. test นี้มี sleep กี่จุด? รวมกี่วินาที?
  2. แต่ละ sleep รอ "อะไร" จริง ๆ?
  3. เขียนใหม่โดยใช้ explicit wait
  4. assertion ข้อ 5, 8, 9, 10 ควรเป็น hard หรือ soft?
ดูคำตอบแนะนำ

1. มี sleep 3 จุด รวม 10 วินาที (3+2+5) ทุกรอบ แม้ระบบจะเร็ว

2.

  • sleep(3000) → รอหน้าสินค้า load เสร็จ
  • sleep(2000) → รอ API add-to-cart ทำงานเสร็จ + UI update
  • sleep(5000) → รอหน้าตะกร้า load เสร็จ

3. เขียนใหม่:

Test: ทดสอบการเพิ่มสินค้าลงตะกร้า

1. เปิดหน้าสินค้า
2. waitUntil: ปุ่ม "เพิ่มลงตะกร้า" visible (timeout 15s)
3. คลิกปุ่ม "เพิ่มลงตะกร้า"
4. waitUntil: badge ตะกร้าแสดงเลข "1" (timeout 10s)
5. assert: badge ตะกร้าแสดงเลข "1"
6. คลิกปุ่ม "ไปหน้าตะกร้า"
7. waitUntil: ชื่อสินค้าแสดงในตะกร้า (timeout 15s)
8. assert: ชื่อสินค้าแสดงในตะกร้า
9. assert: ราคาสินค้าถูกต้อง
10. assert: ปุ่ม "ชำระเงิน" enabled

4.

  • ข้อ 5 (badge) → Hard assertion — ถ้า add-to-cart ไม่สำเร็จ ไปหน้าตะกร้าก็ไม่มีประโยชน์
  • ข้อ 8, 9, 10 (ชื่อ, ราคา, ปุ่ม) → Soft assertion — อยู่ในหน้าเดียวกัน อยากรู้ว่าอะไรผิดบ้างทั้งหมด

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

  • Assertion คือหัวใจของ test — test ที่ไม่มี assertion ไม่มีประโยชน์
  • Hard assertion หยุดทันที ใช้กับ critical checkpoint / Soft assertion ทำต่อ ใช้กับ validation หลายจุด
  • sleep() คือศัตรูของ automation — ทำให้ test ช้าและ flaky
  • Explicit wait รอเท่าที่จำเป็นตาม condition ที่ชัดเจน — เร็วกว่าและเสถียรกว่า
  • ตั้ง timeout ที่เหมาะสม — ไม่สั้นเกินจน fail บ่อย ไม่ยาวเกินจน test ช้า