Selenium Web UI 自動化測試

之前撰寫過一篇 Python Seleium 做動態網路爬蟲 - 在Yahoo!股市爬自動取多個股價 文中有提到,我們可以使用 Python 的套件 Selenium 來做 UI 自動化測試,不過實際是使用 Pytest 這個測試框架來執行 Selenium 的一系列的自動化行為,再檢查這項行為(測試)的動作是不是正確的。

接下來讓我們實際來做做看!

測試 Google 搜尋頁面


打開 Google 搜尋首頁,會先看到幾個必定出現的東西:
  1. 大大的 Google logo 圖片
  2. 一個搜尋欄位,包含欄位中三個 Icon
  3. 搜尋欄位下方兩個按鈕:Google 搜尋 和 好手氣
  4. 左上角兩個按鈕:關於 Google 和 Google 商店
這邊會暫時先撇除下方的顯示欄位以及右上角的服務功能,主要是我覺得上述幾點與我主題比較相關 - 測試UI,不需要全部都做出來(笑)。

不過測試邏輯上我覺得是大同小異,唯一不同就是測試的深度,這可能會包括點擊以後出現的結果、API 和登入的測試,往後再來繼續寫(好像又挖了一個坑)。

安裝 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 底下建立幾項步驟:
  1. 打開 Chrome 的 Webdriver。
  2. 指定開啟的 URL:https://www.google.com/。
  3. 抓取 Google Logo Image 的 Element。
  4. 檢查 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

執行測試的步驟也和上一個測試案例很類似:
  1. 打開 Chrome 的 Webdriver。
  2. 指定開啟的 URL:https://www.google.com/。
  3. 抓取三個 Icon 的 Element。
  4. 檢查三個 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

建立第三個測試項目 - 檢查搜尋欄位下放的按鈕

已經有上述兩個檢查顯示的例子,這次來測試按鈕上面的文字是否顯示正確,而詳細步驟如下:
  1. 打開 Chrome 的 Webdriver。
  2. 指定開啟的 URL:https://www.google.com/。
  3. 抓取兩個按鈕 的 Element。
  4. 檢查兩個按鈕的文字 是否顯示在畫面上。
*註,這邊要注意看一下 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 來拿到文字:
  1. 打開 Chrome 的 Webdriver。
  2. 指定開啟的 URL:https://www.google.com/。
  3. 抓取兩個按鈕 的 Element。
  4. 檢查兩個按鈕的文字 是否顯示在畫面上。
  • 關於 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()),這樣重複性很高的程式碼,可以利用其它更便利的方法來解決這樣的問題,後續再繼續介紹。

完整的程式碼可以參考 Github

張貼留言

較新的 較舊