บทที่ 5: Web Testing ด้วย Browser Library¶
ก่อนอ่านบทนี้ ลองตอบ:¶
- ทำไมต้องแยก keyword ออกเป็น resource file?
- Keyword ที่ return ค่ากลับมาต้องเขียนยังไง?
ลองตอบก่อน แล้วค่อยอ่านต่อ
วัตถุประสงค์¶
อ่านจบแล้วคุณจะ:
- ใช้ Browser Library เปิด browser และ navigate ได้
- หา element ด้วย locator strategy ที่ถูกต้อง (id, css, xpath)
- คลิก, พิมพ์, เลือก dropdown, และ verify ค่าได้
- เขียน explicit wait แทน Sleep ที่ brittle
ทำไมต้องรู้? (Why)¶
Web testing คือ use case หลักของ RF สำหรับ QA ทุกคน
การทดสอบ web ด้วยมือ manual นั้น: - ซ้ำซากและเสียเวลา - มีโอกาสผิดพลาดสูงเมื่อทำซ้ำ - ไม่ scale เมื่อ feature เพิ่มขึ้น
Browser Library (Playwright) แก้ปัญหาเหล่านี้ได้ และยังรองรับ modern web app ที่ใช้ React, Vue, Angular ได้ดีกว่า Selenium มาก
Analogy: Browser Library เหมือน "ผู้ช่วย QA เสมือน"¶
จินตนาการว่าคุณมีผู้ช่วย QA ที่: - เปิด browser และไปหน้าที่กำหนดให้ - มองหา element บน screen ตาม locator ที่บอก - ทำ action เช่น คลิก, พิมพ์, scroll - ตรวจสอบผล ว่าเป็นตามที่คาดหวัง - รอ จนกว่า element จะพร้อม ไม่รีบเกินไป
⚠️ ถ้าเชื่อ analogy นี้ 100% จะเข้าใจผิดว่า: - ผู้ช่วยรู้จัก element เองเหมือนคนจริง — จริงๆ ต้องบอก locator ที่แม่นยำ ถ้า locator เปลี่ยนต้องอัปเดต keyword - "รอ" หมายความว่ารอแบบ Sleep — จริงๆ Browser Library รอ state ของ element (visible, enabled, stable) ซึ่งฉลาดกว่าการรอเวลาตายตัว
Locator Strategies¶
Locator คือวิธีบอกให้ RF หา element บนหน้า web
Priority ในการเลือก Locator (จากดีที่สุดไปแย่ที่สุด)¶
1. id ← เฉพาะที่สุด เปลี่ยนน้อยที่สุด ✓✓✓
2. data-testid ← สร้างมาเพื่อ test โดยเฉพาะ ✓✓✓
3. css ← flexible ใช้ได้กว้าง ✓✓
4. text ← อ่านง่าย แต่เปลี่ยนตาม i18n ✓
5. xpath ← ใช้เมื่อไม่มีทางอื่น ✓ (brittle)
ตัวอย่าง Locator Syntax¶
# By id
Click id:login-btn
Fill Text id:username testuser
# By CSS selector
Click css:button.primary
Fill Text css:input[name='email'] test@example.com
Click css:.nav-menu > li:first-child
# By data-testid (แนะนำมากถ้า dev สร้างไว้ให้)
Click data-testid=submit-button
Fill Text data-testid=email-input user@example.com
# By text content
Click text=Login
Click text=ยืนยัน
# By XPath (ใช้เฉพาะกรณีจำเป็น)
Click xpath=//button[@type='submit']
Fill Text xpath=//input[@placeholder='Email address'] test@example.com
Keywords หลักของ Browser Library¶
เปิด/ปิด Browser¶
Navigate¶
Fill และ Click¶
Verify¶
# ตรวจสอบ text บนหน้า
Get Text id:welcome-msg == Welcome, testuser
# ตรวจสอบว่า element มี/ไม่มี
Wait For Elements State id:error-msg visible
Wait For Elements State id:spinner hidden
# ตรวจสอบ title
Get Title == Dashboard - MyApp
# ตรวจสอบ URL
Get Url contains /dashboard
Wait (สำคัญมาก!)¶
# รอจนกว่า element จะ visible
Wait For Elements State id:result visible
# รอจนกว่าจะ enabled (กดได้)
Wait For Elements State id:submit-btn enabled
# รอจนกว่าจะ hidden (loading หาย)
Wait For Elements State id:loading hidden
# รอจนกว่า network request จะเสร็จ
Wait For Navigation
ตัวอย่าง 3 ระดับ¶
Beginner — เปิด browser และตรวจสอบหน้าเว็บ¶
# tested: Robot Framework 7.4.2, Browser Library 19.x
# หมายเหตุ: ต้องติดตั้ง Browser Library และรัน rfbrowser init ก่อน
*** Settings ***
Library Browser
*** Test Cases ***
Open Example Website And Verify Title
[Documentation] เปิด browser และตรวจสอบ title ของหน้า
New Browser chromium headless=True
New Page https://example.com
Get Title == Example Domain
Get Text css:h1 == Example Domain
[Teardown] Close Browser
Intermediate — Login flow สมบูรณ์¶
# tested: Robot Framework 7.4.2, Browser Library 19.x
# ใช้ demo app: https://the-internet.herokuapp.com/login
*** Settings ***
Library Browser
*** Variables ***
${BASE_URL} https://the-internet.herokuapp.com
${VALID_USER} tomsmith
${VALID_PASS} SuperSecretPassword!
*** Test Cases ***
Valid Login Shows Success Message
[Documentation] Login ด้วย credential ที่ถูกต้องและตรวจสอบ success message
[Tags] login smoke
Open Login Page
Enter Credentials ${VALID_USER} ${VALID_PASS}
Login Success Should Be Shown
[Teardown] Close Browser
Invalid Login Shows Error Message
[Documentation] Login ด้วย password ผิดและตรวจสอบ error message
[Tags] login negative
Open Login Page
Enter Credentials ${VALID_USER} wrongpassword
Login Error Should Be Shown Your password is invalid!
[Teardown] Close Browser
*** Keywords ***
Open Login Page
New Browser chromium headless=True
New Page ${BASE_URL}/login
Wait For Elements State id:username visible
Enter Credentials
[Arguments] ${username} ${password}
Fill Text id:username ${username}
Fill Text id:password ${password}
Click css:button[type='submit']
Login Success Should Be Shown
Wait For Elements State css:.flash.success visible
Get Text css:.flash.success contains You logged into a secure area
Login Error Should Be Shown
[Arguments] ${expected_message}
Wait For Elements State css:.flash.error visible
Get Text css:.flash.error contains ${expected_message}
Advanced — Test ที่จัดการ dynamic content¶
# tested: Robot Framework 7.4.2, Browser Library 19.x
# ใช้ demo app: https://the-internet.herokuapp.com
*** Settings ***
Library Browser
Library Collections
*** Variables ***
${BASE_URL} https://the-internet.herokuapp.com
*** Test Cases ***
Dynamic Content Loads Correctly
[Documentation] ตรวจสอบว่า dynamic content โหลดมาถูกต้อง
[Tags] dynamic intermediate
New Browser chromium headless=True
New Page ${BASE_URL}/dynamic_content
Wait For Elements State css:.large-4 visible
${items}= Get Elements css:.large-4
Length Should Be ${items} 3
[Teardown] Close Browser
Disappearing Elements Test
[Documentation] ทดสอบหน้าที่ element หายไปและกลับมา
[Tags] dynamic advanced
New Browser chromium headless=True
New Page ${BASE_URL}/disappearing_elements
${nav_items}= Get Elements css:ul li
${count}= Get Length ${nav_items}
Should Be True ${count} >= 4
Log พบ navigation items: ${count} รายการ
[Teardown] Close Browser
*** Keywords ***
Wait For Page To Fully Load
Wait For Elements State css:body visible
Sleep 0.5s # minimal wait สำหรับ animation
Sleep vs Wait — ทำไม Sleep เป็น bad practice¶
# ❌ แบบผิด — brittle และช้า
Login Test
Click id:login-btn
Sleep 3 seconds # รอแบบตายตัว ถ้า network ช้า = fail
Page Should Contain Welcome
# ✅ แบบถูก — รอแบบ smart
Login Test
Click id:login-btn
Wait For Elements State id:welcome-banner visible timeout=10s
Get Text id:welcome-banner contains Welcome
เหตุผล:
- Sleep ทำให้ test ช้า — รอ 3 วินาทีทุกครั้ง แม้ page load ใน 0.5 วินาที
- Sleep ทำให้ test brittle — ถ้า server ช้าวันไหน 3 วินาทีไม่พอ fail เลย
- Wait For Elements State รอแบบ adaptive — ได้แล้วรัน, timeout แล้วค่อย fail พร้อม error ที่ชัดเจน
(source: Browser Library Best Practices)
Common Mistakes¶
❌ ใช้ XPath ที่ขึ้นกับ position เช่น //div[3]/span[2]
# ผิด — เปราะบาก เปลี่ยน layout = fail
Click xpath=//div[3]/span[2]/button
# ถูก — ใช้ attribute ที่มีความหมาย
Click css:button[data-action='checkout']
# หรือ
Click id:checkout-btn
❌ ไม่ปิด Browser ใน Teardown
# ผิด — ถ้า test fail browser ค้างอยู่
My Test
New Browser chromium
New Page ${URL}
# ... test ...
Close Browser ← ถ้า test fail บรรทัดนี้ไม่รัน
# ถูก — ใช้ Teardown รับประกันว่าจะรันเสมอ
My Test
New Browser chromium
New Page ${URL}
# ... test ...
[Teardown] Close Browser
❌ Hardcode locator ซ้ำหลายที่
# ผิด — ถ้า id เปลี่ยนต้องแก้หลายที่
Test 1
Click id:add-to-cart-button
Test 2
Wait For Elements State id:add-to-cart-button visible
# ถูก — ใช้ variable
*** Variables ***
${ADD_TO_CART} id:add-to-cart-button
Test 1
Click ${ADD_TO_CART}
Test 2
Wait For Elements State ${ADD_TO_CART} visible
สรุปบท¶
ก่อนไปบทต่อไป ลองตอบ (คิด 30 วินาทีก่อนดูเฉลย):
คำถาม 1: ถ้าหน้า web มีปุ่ม Login ที่มี id="btn-login" และ class="btn-primary" คุณจะใช้ locator แบบไหน? เพราะอะไร?
คำถาม 2: ความแตกต่างระหว่าง Sleep 3 seconds กับ Wait For Elements State id:result visible คืออะไร? อันไหนดีกว่าในสถานการณ์ใด?
คำถาม 3: ทำไม [Teardown] Close Browser ถึงดีกว่าการใส่ Close Browser ไว้ท้าย test case?