之前撰寫過一篇 Python Seleium 做動態網路爬蟲 - 在Yahoo!股市爬自動取多個股價 文中有提到,我們可以使用 Python 的套件 Selenium 來做 UI 自動化測試,不過實際是使用 Pytest 這個測試框架來執行 Selenium 的一系列的自動化行為,再檢查這項行為(測試)的動作是不是正確的。
接下來讓我們實際來做做看!
測試 Google 搜尋頁面
安裝 webdriver-manager
之前,使用 Pip install Selenium 的話,會需要另外下載相應的瀏覽器 Webdriver,這樣非常麻煩!只要版本一更新,就必須去下載新的 Webdriver。
$ pip install webdriver-manager
現在,可以使用 Pip install webdriver-manager,它可以在每一次 Webdriver 有新版本的時候,會為你自動更新 Webdriver,更棒的地方,你只需要幾行的程式輕鬆搞定。
# selenium 3 from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager driver = webdriver.Chrome(ChromeDriverManager().install())
安裝 pytest
本篇不會用到太多 Pytest 的功能,所以先簡單介紹一下,之後感覺可以好好地介紹一下這個工具。
$ pip install pytest
今天會用到的功能如下:
- 每一個 Python file 要以 test 為開頭命名,例如 test_google_page.py。
- 定義的 Class也以 Test為開頭命名,例如 TestGooglePage()。
- 定義的 Function 也以 test 為開頭命名,例如 test_google_logo_image()。
建立第一個測試項目 - 檢查 Google logo image
先以最簡單的方式來理解如何使用 Pytest 和 selenium。
首先,先定義一個 Function 叫做 test_google_logo_image(),要在這個 test function 底下建立幾項步驟:
- 打開 Chrome 的 Webdriver。
- 指定開啟的 URL:https://www.google.com/。
- 抓取 Google Logo Image 的 Element。
- 檢查 Google Logo Image 是否顯示在畫面上。
def test_google_logo_image(): driver = webdriver.Chrome(ChromeDriverManager().install()) driver.get("https://www.google.com/")
🤔 如何抓取 Google logo image 的 Element ?
最簡單的方法就是開啟 Google Chrome 的檢查頁面直接選取 Image 並複製 XPath 即可,想要確保 Element 是完整的路徑,可以選擇 Copy full XPath,會得到 /html/body/div[1]/div[2]/div/img。
🤔 如何確定 Google logo image 有正確顯示 ?
測試的方式很多種,最簡單的方式就是檢查圖片是否有顯示在畫面上,可以用 is_displayed() 來檢查,如果有顯示會返回 True,相反這個元件沒有出現在畫面上則是 False。
def test_google_logo_image(): driver = webdriver.Chrome(ChromeDriverManager().install()) driver.get("https://www.google.com/")
google_image_element = '/html/body/div[1]/div[2]/div/img'
google_image = driver.find_element(By.XPATH,
google_image_element).is_displayed()
assert google_image is True
🤔 如何確定檢查 Google logo image 有顯示 ?
在這個 test function 最後面可以加上一個 assert,用於判斷一個表達式,在這個表達式條件如果呈現 False 的時候才會觸發異常。
對於 Pytest 來說,當執行這項 test_google_image() 測試時,如果 assert 出現 False 時,表示測試結果有跟我們預期的答案發生錯誤,如果為 True 就是符合(成功)的意思。
也就是說,定義這個 test function 的一開始就確定要測試的結果,這項測試定義為確認圖片是否正確顯示,所以 assert google_image is True。
建立第二個測試項目 - 檢查搜尋欄位內的三個 Icon
執行測試的步驟也和上一個測試案例很類似:
- 打開 Chrome 的 Webdriver。
- 指定開啟的 URL:https://www.google.com/。
- 抓取三個 Icon 的 Element。
- 檢查三個 Icon 是否顯示在畫面上。
抓取 icon 的 element 方法是一樣的:
- 左邊放大鏡:/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[1]/div/span
- 右邊麥克風:/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[3]/div[2]
- 最右邊相機:/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[3]/div[3]/img
有了這三個 Element 就可以來寫一支測試程式了。
def test_three_icon_in_search_field(): driver = webdriver.Chrome(ChromeDriverManager().install()) driver.implicitly_wait(10) driver.get("https://www.google.com/") magnifier_icon_element = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[1]/div/span" mic_icon_element = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[3]/div[2]" camera_icon_element = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[3]/div[3]/img" magnifier_icon = driver.find_element(By.XPATH, magnifier_icon_element).is_displayed() mic_icon = driver.find_element(By.XPATH, mic_icon_element).is_displayed() camera_icon = driver.find_element(By.XPATH, camera_icon_element).is_displayed() assert magnifier_icon is True and mic_icon is True and camera_icon is True
建立第三個測試項目 - 檢查搜尋欄位下放的按鈕
已經有上述兩個檢查顯示的例子,這次來測試按鈕上面的文字是否顯示正確,而詳細步驟如下:
- 打開 Chrome 的 Webdriver。
- 指定開啟的 URL:https://www.google.com/。
- 抓取兩個按鈕 的 Element。
- 檢查兩個按鈕的文字 是否顯示在畫面上。
*註,這邊要注意看一下 Element,它把 Google 搜尋 的字樣存在 aria-label 裡面,所以擷取的方式會有一些不同。
一般來說,如果要抓取文字只需要 find_element(By.XPATH, '<element>').text 就可以取得,在這個例子中,需要改成使用 get_attribute('aria-label') 來取得文字。
- Google 搜尋按鈕:/html/body/div[1]/div[3]/form/div[1]/div[1]/div[4]/center/input[1]
- 好手氣按鈕:/html/body/div[1]/div[3]/form/div[1]/div[1]/div[4]/center/input[2]
抓到 Element 之後,就可以來撰寫測試程式了:
def test_two_button_under_search_field():
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.implicitly_wait(10)
driver.get("https://www.google.com/")
google_search_btn_element = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[4]/center/input[1]"
lucky_btn_element = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[4]/center/input[2]"
google_search_btn = driver.find_element(By.XPATH, google_search_btn_element).get_attribute('aria-label')
assert google_search_btn == "Google 搜尋"
lucky_btn = driver.find_element(By.XPATH, lucky_btn_element).get_attribute('aria-label')
assert lucky_btn == "好手氣"
建立第四個測試項目 - 檢查 關於 Google 和 Google 商店按鈕
根據上述的例子,取得文字的方式是使用 get_attribute('aria-label'),觀察一下左上角兩個按鈕的 Element 是把文字存放在 tag 外面,這時候可以使用 .text 來拿到文字:
- 關於 Google:/html/body/div[1]/div[1]/a[1]
- Google 商店:/html/body/div[1]/div[1]/a[2]
抓到 Element 之後,就可以來撰寫測試程式了:
def test_google_btn_upper_left_corner():
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.implicitly_wait(10)
driver.get("https://www.google.com/")
about_google_element = "/html/body/div[1]/div[1]/a[1]"
google_store_element = "/html/body/div[1]/div[1]/a[2]"
google_search = driver.find_element(By.XPATH, about_google_element).text
assert google_search == "關於 Google"
google_store = driver.find_element(By.XPATH, google_store_element).text
assert google_store == "Google 商店"
以上就是使用 Pytest 結合 Selenium 的 UI 測試範例,寫這些測試案例時,有發現一個問題,每一個案例都得寫一次 driver = webdriver.Chrome(ChromeDriverManager().install()),這樣重複性很高的程式碼,可以利用其它更便利的方法來解決這樣的問題,後續再繼續介紹。