ทำ Test Automation ด้วย Selenium
Selenium
คือเครื่องมือที่ควบคุมการทำงานของ Browser มีไว้สำหรับทำ automated testing ซึ่ง Selenium สามารถพํฒนาได้ภาษาต่างๆเหล่านี้
- Java
- Python
- C#
- Javascript
- Ruby
- PHP
นอกจาก Automated Testing แล้ว selenium ยังสามารถนำไปใช้ในการทำ
- Robot Process Automation(RPA) สร้าง Bot เพื่อทำงานซ้ำๆแทนคน
- Web scraping เป็น Bot ที่เข้าไปเก็บข้อมูลบน Website ต่างๆ
แต่แน่นอนการทำ RPA และ Web scraping ไม่ได้เป็นตลาดใหญ่ของ Selenium เพราะ Selenium โ่ด่งดังขึ้นมาจากการทำ Automated Test ซึ่งถ้าคุณเข้าใจการทำงานของ Selenium ก็สามารถนำไปประยุกต์ใช้กับ RPA และ Web Scraping ได้ไม่ยาก
Selenium มี products ย่อยๆอยู่ 3 ตัวดังนี้
- Selenium IDE ทำหน้าที่บันทึกการทำงานของ UI(record)
- Selenium Webdriver เป็นเครื่องมือหลักที่เราใช้ควบคุม Browser
- Selenium Grid ช่วยให้ Selenium ทำงานเร็วขึ้น เนื่องจาก Selenium Grid จะทำแบบ Parallel(ทำพร้อมกันหลายๆงาน)
เราจะเลือกใช้ Selenium IDE หรือ Selenium Webdriver ในการสร้าง Test script แต่เราจะใช้ Selenium Grid ในการนำไป run test
Selenium ประกอบไปด้วยเครื่องมือย่อยๆ 3 ตัวดังนี้
Selenium IDE
Selenium IDE คือ Browser extension ที่ติดตั้งเข้าไปใน Browser เพื่อบันทึกการทำงานและสามารถแทรก Assert เข้าไปเพื่อทดสอบการทำงานของ Web หน้านั้นๆได้ เช่น เมื่อกดปุ่มค้นหาแล้วมีรายการสินค้าที่เราต้องการโผล่ขึ้นมาหรือไม่ Selenium IDE สามารถติดตั้งได้ทั้ง Chrome และ Firefox
ข้อดีและข้อเสียของ Selenium IDE
ประโยชน์ที่เราได้จาก Selenium IDE คือ
- สามารถเขียน Test script ได้อย่างรวดเร็ว
- Selenium IDE ใช้การ Generate action ต่างๆที่เราทำออกมาเป็น Test script
- มี UI ที่สสามารถเริ่มต้นใช้งานได้ง่าย
- เหมาะสำหรับ QA ที่ไม่ชอบการเขียนโปรแกรม
ข้อเสียของ Selenium IDE คือ
- ความสามารถของ Selenium IDE มีจำกัด
- Test script ที่ generate ออกมามีความซ้ำซ้อน
- Test script ที่ได้อาจไม่สวยงาม อ่านยาก และแก้ไขได้ยาก
- Test script จะไม่สามารถสร้างเงื่อนไข หรือวน loop ได้
อ่านวิธีการติดต้ังและใช้งาน Selenium IDE ได้ที่บทความนี้
Selenium Webdriver
เป็นการเขียน script เข้าไปควบคุมการทำงานของ browser โดยตรง ซึ่งก่อนจะควบคุม browser ได้ เราจำเป็นต้องติดตั้ง driver ก่อน เช่น ถ้าต้องการควบคุม Chrome เราต้องติดตั้ง Chromedriver
การเขียนคำสั่งต่างๆเข้าไปควบคุม browser เรียกว่า Web driver’s API ซึ่งข้อเสียของ Web driver’s API คือจะเขียนยากมี syntax ให้ต้องเรียนรู้อยู่เยอะมาก
ติดตั้ง Selenium Webdriver
สิ่งที่ต้องติดตั้งก่อนการใช้งาน Selenium Webdriver มีดังนี้
-
Test Runner และ Assertion Library ทำหน้าที่ run test script ซึ่งจะขึ้นอยู่กับภาษาที่เราเลือกมาเขียน เช่น ถ้าเขียนด้วย Python ก็จะต้องใช้ pytest ในการ run test script
และใน Test runner ต้องการ Assertion Library ซึ่งบางตัวจะติดตั้งมาด้วยกัน บางตัวอาจต้องมีการติดตั้ง Library แยกต่างหาก
-
Web Driver Library เป็น Library สำหรับคำสั่งที่ต่างๆที่เราจะใช้เขียน Test script ดูตัวอย่างการเขียน Selenium Webdriver ด้วย Python
-
Driver เป็น driver สำหรับควบคุมการทำงานของ Browser ซึ่งต้องอ้างอิงตาม Browser ที่เราจะใช้ทดสอบ ซึ่งเราสามารถ Download Selenium Webdriver ได้ตาม Link ด้านล่างนี้
ปัญหาของการใช้งาน Selenium คือต้องตาม update driver ทุกครั้งที่ browser update ซึ่งหลังจาก Selenium 4.6 เป็นต้นไป เราจะมี Selenium Manager คอยดูแลการ install และ update driver ให้เรา
ข้อควรระวัง ถ้าเรา add PATH ของ driver ไว้ใน Environment Variable(เราติดตั้ง driver เอง) Selenium Manager จะไม่ทำงาน เราต้องคอย update driver เองเหมือนเดิม และอีกปัญหาที่เราจะเจอบ่อยๆคือ เครื่องที่ run test ต้องออก internet ได้ และไม่ถูก block การ download ด้วย firewall
ข้อแนะนำ ถ้ามี selenium driver ที่ติดต้ังมาก่อนหน้านี้ให้ remove ออกแล้วให้ Selenium Manager คอยดูแลเรื่อง version ให้เรา
การติดตั้ง Selenium นั้นจะมีขั้นตอนเยอะกว่า Automated Testing Framework ตัวอื่นๆ อย่าง Playwright และ Cypress เพราะต้องมีการติดตั้ง Driver นี่แหละ นี่เป็นสิ่งที่ Selenium พยายามปรับตัวเพื่อแข่งขันกับ Playwright และ Cypress
เขียน Selenium Webdriver ด้วย Python
Python เป็นหนึ่งในภาษาที่ถูกนำมาใช้เขียน Test script มากที่สุด และ Selenium ก็ support python เช่นเดียวกับ Framework อื่นๆ ในตัวอย่างนี้เราจะเขียน test script เพื่อควบคุมการทำงานของ browser ผ่านทาง Web Driver ด้วย python แบบเบื้องต้นกัน
เริ่มจากการเขียน Test script จะมีโครงสร้างดังนี้
-
import webdriver เข้ามาใช้งาน
import webdriver
-
load webdriver ขึ้นมาด้วยคำสั่ง
driver = webdriver.Chrome()
-
เข้าไปยังหน้า Web ที่ต้องการทดสอบ ด้วยคำสั่ง
driver.get("https://codinggun.com")
-
รอจนกว่าหน้า Web จะ load เสร็จด้วยคำสั่ง Wait
driver.implicitly_wait(0.5)
จุดนี้จะต้องกำหนดค่าให้เหมาะสมกับระยะเวลาที่ใช้ในการ load หน้า web ถ้า net เราช้าต้องใช้เวลาในการ load หน้า web นานจะต้องกำหนด implicitly_wait ให้มากขึ้น
อ่านการใช้คำสั่ง Wait ใน Selenium ต่อได้ที่นี่
-
ค้นหา element ที่ต้องการด้วยคำสั่ง
btn = driver.find_element(By.ID, "btnSubmit")
ดูคำสั่งที่ใช้ในการค้นหา Web elements อื่นๆได้ที่นี่
-
ส่งคำสั่งเข้าไปควบคุมการทำงานของ Element นั้น
btn.click()
ดูคำสั่งที่ใช้ควบคุมการทำงานของ browser อื่นๆต่อได้ที่นี่
-
จบการทำงานของ Webdriver ด้วยคำสั่ง
driver.quit()
สุดท้ายแล้วเราจะได้ตัวอย่าง Test script ที่เขียนด้วย python หน้าตาแบบนี้
|
|
การใช้คำสั่ง Wait ใน Selenium
การใช้คำสั่ง Wait เป็นสิ่งที่ต้องทำความเข้าใจ เพราะเป็นสิ่งที่จะทำให้เกิด flaky test(การทดสอบที่ได้ผลลัพธ์แตกต่างกันในแต่ละครั้งที่ run test)
ใน Selenium จะแบ่งประเภทของการ Wait ออกเป็น 2 ประเภท ดังนี้
-
Implicit Wait Selenium จะ delay การทำงานออกไปตามระยะเวลาที่เรากำหนด โดยจะไม่ได้สนใจว่า Elements ที่เราต้องการนั้นถูก load ขึ้นมารึยัง ตัวอย่างของ implicit wait จะเป็นดังนี้
driver.implicitly_wait(2)
ค่า default ของ implicitly_wait จะเป็น 0 นั่นหมายความว่าถ้าเราไม่กำหนด Implicit wait หรือ Explicit wait ใน script ของเรา Selenium จะเข้าไปค้นหา Web elements ด้วยคำสั่ง find_element ทันที ซึ่งจะทำให้เกิด error เพราะ Web elements นั้นจะ load ไม่ทัน
-
Explicit Wait Selenium จะทำการ delay การทำงานพร้อมกับการตรวจสอบ element ที่เราค้นหา โดยจะวน loop ไปเรื่อยๆจนกว่า element ที่เราต้องการจะถูก load ขึ้นมา ตัวอย่างของ Explicit Wait จะเป็นดังนี้
1 2 3 4 5 6
btn = driver.find_element(By.ID, "btnSubmit") wait = WebDriverWait(driver, timeout=2) wait.until(lambda d : btn.is_displayed()) btn.click()
code หลังจากบรรทัด wait_until จะถูก run ก็ต่อเมื่อปุ่มที่มี ID เป็น btnSubmit ถูก load ขึ้นมา
ข้อควรระวัง ไม่ควรใช้ Implicit และ Explicit waits ร่วมกัน ควรเลือกใช้แค่ตัวใดตัวหนึ่งเท่านั้น
ค้นหา Web Elements
การทดสอบเราจำเป็นต้องใช้ Locators ในการค้นหา Web element ที่ต้องการเพื่อนำไปใส่ข้อมูล หรือ trigger events ต่างๆ เช่น click ปุ่ม submit
ใน Selenium สามารถใช้ locators ได้หลายรูปแบบ ซึ่งจะแบ่งออกเป็นรูปแบบต่างๆ ดังนี้
ตัวอย่าง ของ HTML ที่เราจะใช่้ทำการทดสอบเป็นแบบนี้
<button id="btnSubmit" name="btnSubmit" class="btn-mb-2">
Submit
</button>
-
ID ถ้าต้องการหา web element ด้วย ID เราจะใช้คำสั่ง
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.ID, "btnSubmit")
-
Name ถ้าต้องการหา web element ด้วย attribute name เราจะใช้คำสั่ง
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.NAME, "btnSubmit")
-
Tag Name ถ้าต้องการค้นหา web element ตามชื่อ tag ให้ใช้คำสั่ง
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.TAG, "button")
-
Class Name ถ้าต้องการค้นหา web element ด้วย CSS Class เราจะใข้คำสั่ง
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.CLASS_NAME, "btn-mb-2")
-
CSS Selector ถ้าเราต้องการค้นหา web element ด้วย CSS selector เราต้องใช้คำสั่ง
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.CSS_SELECTOR, "#btnSubmit")
ในตัวอย่างนี้จะค้นหา html tag ที่มี id เป็น btnSubmit
-
XPath Selector ถ้าเราต้องการค้นหา web element ด้วย xpath เราจะใช้คำสั่ง
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.XPATH, "//button[text()='Click Me'])
ในตัวอย่างนี้จะค้นหา tag button ที่มีข้อความว่า Click Me
ในการทำงานจริงเราจะเข้าไปที่ Chorme Development Tools และ click ขวาบน Element ที่เราต้องการแล้วเลือก Copy XPath ดังรูป
-
Link Text และสำหรับ Link text เราจะใช้ค้นหา anchor tag ที่มีข้อความที่เรากำหนด ยกตัวอย่างถ้าเรามี HTML แบบนี้
<div> <a href="...">Click Me</a> <a href="...">Click This Text</a> </div>
เราจะต้องเขียน python เพื่อค้นหา element ที่เราต้องการแบบนี้
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.LINK_TEXT, "Click Me")
ถ้าเราใช้ Link Text ข้อความที่ค้นหาต้องถูกต้องแบบเป๊ะๆเลย
-
Partial Link Text จะเหมือนกับ Link Text แต่ว่าใช้ส่วนใดส่วนหนึ่งของข้อความในการค้นหา(substrings) จากตัวอย่าง HTML ด้านบน เราจะเขียน python เพื่อค้นหา element ออกมาแบบนี้
WebDriver driver = new ChromeDriver(); btn = driver.find_element(By.PARTIAL_LINK_TEXT, "Click")
ในตัวอย่างนี้เราจะได้่ elements ออกมา 2 elements ทั่้ง Click Me และ Click This Text
ทำงานกับ Web Elements
หลังจากที่เราได้ Element ที่ต้องการมาแล้วเราจะต้อง สั่งให้มันทำงานด้วยคำสั่ง
Click
ถ้าต้องการให้ปุ่ม Click Me ถูก click เราจะต้องเขียน script แบบนี้
driver.find_element(By.ID, "btnSubmit").click()
Clear
ถ้าเราต้องการ clear input ก่อนจะกรอกข้อมูลลงไป เราจะเขียน script แบบนีั้
driver.find_element(By.NAME, "email").clear()
Send Keys
ถ้าเป็น tag input ที่เราต้องกรอกค่าต่างๆลงไปเราจะเขียน script แบบนี้
driver.find_element(By.NAME, "email").send_keys("admin@localhost.dev" )
Selenium Grid
Selenium Grid คือเครื่องมือที่ช่วยให้เรา run Test Script พร้อมๆกันแบบคู่ขนาน(parallel) เพราะปัญหาของการทำ UI Testing คือความช้า ถ้าเราต้องการทดสอบหลายๆ workflow พร้อมๆกัน เราก็จะใช้ Selenium Grid มาช่วยแตก process แล้วกระจายไปยังเครื่องต่างๆ(Nodes)
และนอกจากความเร็วที่เราจะได้จาก Selenium Grid แล้วเรายังสามารถแยกการทดสอบด้วย Browser หลายๆตัว หรืออาจเป็นการทดสอบ Browser ตัวเดียวกันแต่หลาย version ก็ได้
ซึ่ง Selenium Grid จะแบ่งออกเป็น 2 components คือ
- Hub เป็นตัวกระจายงานออกไปยัง Node ต่างๆ ทำหน้าที่เป็น controller คอยควบคุมการทำงาน ซึ่งใน 1 grid จะมี 1 hub เท่านั้น
- Nodes เครื่องที่ใช้ทดสอบ จะมีได้หลายตัว(เป็น VM หรือ Container) และหลาย environments ขึ้นอยู่กับสิ่งที่เราต้องการทดสอบ
Client ที่อยู่ใสรูปอาจเป็น Test script ที่เขียนด้วย python,java,c#,javscript,ruby,php หรืออาจเป็น task งานที่อยู่ใน CI/CD pipelines อย่าง Jenkins, Gitlab CI หรือ Azure DevOps ก็ได้
การ deploy Node สำหรับ run test เราจะเลือกใช้ Container หรือ Virtual Machine(VM) ก็ได้
โดยสรุปข้อดีของการใช้ Selenium Grid คือ
- กระจายงาน(task) ออกไปยัง Node ต่างๆ
- ทดสอบแบบเดียวกันบน Browser หลายๆตัวพร้อมๆกัน
- ทดสอบแบบเดียวกันบน Browser เดียวกันแต่หลาย version
อีกทางเลือกนึงที่เราสามารถนำมาใช้แทน Selenium Grid คือ CI/CD pipeline ซึ่งจะสามารถแตก task ได้ง่ายกว่า รวมทั้งยัง support container อยู่แล้ว ทีมไหนที่มี CI/CD pipeline แนะนำให้แตก Task ใน Pipeline แทนการใช้งาน Selenium Grid
Robot Framework
ในกรณีที่เราใช้ Robot Framework เราจะต้องติดตั้ง SeleniumLibrary เพื่อให้สามารถใช้ keyword ต่างๆควบคุมการทำงานของ browser ได้
ตัวอย่างการเขียน Robot script ด้วย SeleniumLibrary
|
|
อ่านวิธีการใช้ Robot Framework ต่อได้ที่นี่