[Web] 使用 Selenium web driver 作 web automation

[Web] 使用 Selenium web driver 作 web automation

在 使用 Selenium IDE 來做簡單的 web automation 這篇文章中,

曾經提過一個用 Selenium IDE 來做出自動匯出痞客邦網誌的自動化程式~

不過那個麻煩的點是還要自己開啟 Firefox + Selenium IDE,

選擇那個 test case 執行才行,有點不便…

要能更好的自動化,就需要用上 Selenium web driver 了~

它可以讓我們直接用程式 (如 python) 的方式,指揮 Selenium 來操控瀏覽器~

 

1. 安裝 Selenium web driver for Firefox

Python bindings for selenium 是一個讓 python 可以操控 Selenium 的套件,

裡面會含有給 Firefox 用的 web driver

直接用 pip install selenium 就能安裝了: 

testuser@localhost ~ $ pip install selenium
Downloading/unpacking selenium
Downloading selenium-2.45.0.tar.gz (2.6MB): 2.6MB downloaded
Running setup.py (path:/private/var/folders/qg/l7_9f_4x707br0gghptzfs0cjr0hkh/T/pip_build_jeff_lai/selenium/setup.py) egg_info for package selenium
Installing collected packages: selenium
Running setup.py install for selenium
Successfully installed selenium
Cleaning up...

 

要確認安裝成功,只要看看 python 能不能 import selenium 這個 module 就行了:

testuser@localhost ~ $ python
>>> import selenium
>>>

 

2. 將 Selenium IDE 的 test case 匯出成 python 程式

在 Selenium IDE 選擇 File > Export Test Case As > Python 2 / unittest / WebDriver,

就可以將 test case 匯出成 python 的程式:

Screen Shot 2015-03-18 at 上午12.07.58  

 

匯出後的 python 程式是一個 unittest 程式,在 setUp() 裡建立了 Firefox() 物件,

而主要的邏輯是在 test_xxx() 那個函式裡,例如我匯出的是像下面這樣:

def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.pixnet.net/"
self.verificationErrors = []
self.accept_next_alert = True
def test_export_pixnet_webdriver(self):
driver = self.driver
driver.get("http://panel.pixnet.cc/logout")
driver.get(self.base_url + "/?done=http%3A%2F%2Fephrain.pixnet.net%2Fblog")
driver.find_element_by_id("input-username").clear()
driver.find_element_by_id("input-username").send_keys("myusername")
driver.find_element_by_id("input-password").clear()
driver.find_element_by_id("input-password").send_keys("mypassword")
driver.find_element_by_id("login-send").click()
driver.get("http://panel.pixnet.cc/blog/export")
driver.find_element_by_id("next-button").click()
# ERROR: Caught exception [Error: locator strategy either id or name must be specified explicitly.]
self.assertEqual(u"備份檔產生完成,請按右下角「下載備份檔」下載您的備份檔", self.close_alert_and_get_its_text())
driver.find_element_by_id("export-status-submit").click()

 

匯出的程式裡有一段詭異的「ERROR: Caught exception [Error: locator strategy either id or name must be specified explicitly.]」

跟 Selenium IDE 裡的步驟對照一下,應該是 assertAlert 這個動作~

 

試著利用程式原有的 is_alert_present() 函式來檢查是否 alert 視窗已經出現,

可是它在 Firefox 上總是傳回 True…

如果是改成 self.driver.switch_to_alert().text 會丟出 NoAlertPresentException,

問題是第二次呼叫時就會莫名其妙的卡住,動彈不得…

在網路上查了一下,似乎也有不少人遇到 alert 會卡住的問題,

試了各種不同的方法,最後發現在 Chrome 上沒有這個問題!!

那就改用 Chrome 版的 web driver 吧~

 

3. 安裝給 Chrome 用的 Selenium web driver

可以到 ChromeDriver 官網看看說明,

我抓的是目前最新的 Chrome driver v2.14 for Mac

下載後是一個 chromedriver_mac32.zip 檔案,

解開後把 chromedriver 放到 $PATH 找的到的目錄下 (例如 /usr/local/bin)~

unzip chromedriver_mac32.zip -d /usr/local/bin/

 

4. 改用 Chrome 版的 web driver

要 Selenium 改用 Chrome 來開啟網頁,只要把 setUp() 裡面初始化 self.driver 那行改掉就行了,

原本是 webdriver.Firefox() 改成 webdriver.Chrome():

def setUp(self):
# self.driver = webdriver.Firefox()
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(30)
self.base_url = "https://www.pixnet.net/"
self.verificationErrors = []
self.accept_next_alert = True

 

將這 python 程式再執行一次,在 Firefox 上會卡住的 self.driver.switch_to_alert().text,

在 Chrome 上就執行的很正常,因此我加了下面這段,

來判斷 alert 視窗是不是已經出現了:

while True:
try:
self.driver.switch_to_alert().text
break
except:
print "Waiting for alert window..."
time.sleep(1)

 

下面提供完整的 python 程式供有興趣的人參考囉~

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
class ExportPixnetWebdriver(unittest.TestCase):
def setUp(self):
# self.driver = webdriver.Firefox()
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(30)
self.base_url = "https://www.pixnet.net/"
self.verificationErrors = []
self.accept_next_alert = True
def test_export_pixnet_webdriver(self):
driver = self.driver
driver.get("http://panel.pixnet.cc/logout")
driver.get(self.base_url + "/?done=http%3A%2F%2Fephrain.pixnet.net%2Fblog")
driver.find_element_by_id("input-username").clear()
driver.find_element_by_id("input-username").send_keys("myuser")
driver.find_element_by_id("input-password").clear()
driver.find_element_by_id("input-password").send_keys("mypassword")
driver.find_element_by_id("login-send").click()
driver.get("http://panel.pixnet.cc/blog/export")
driver.find_element_by_id("next-button").click()
while True:
try:
self.driver.switch_to_alert().text
break
except:
print "Waiting for alert window..."
time.sleep(1)
self.assertEqual(u"備份檔產生完成,請按右下角「下載備份檔」下載您的備份檔", self.close_alert_and_get_its_text())
driver.find_element_by_id("export-status-submit").click()
print "Download file within 10 seconds..."
time.sleep(10)
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException, e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException, e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()

 

 

 

(本頁面已被瀏覽過 1,865 次)

One thought on “[Web] 使用 Selenium web driver 作 web automation

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料