WebDriver基礎
歡迎閱讀WebDriver基礎講義。本篇講義將會重點介紹Selenium WebDriver的環(huán)境搭建和基本使用方法。
WebDriver環(huán)境搭建
Selenium WebDriver 又稱為 Selenium2。
Selenium 1 + WebDriver = Selenium 2
WebDriver是主流Web應用自動化測試框架,具有清晰面向對象 API,能以最佳的方式與瀏覽器進行交互。
支持的瀏覽器:
Mozilla Firefox
Google Chrome
Microsoft Internet Explorer
Opera
Safari
Apple iPhone
Android browsers
環(huán)境搭建步驟
在上一篇中,我們已經(jīng)確認使用Python來進行WebDriver的編碼和操作。事實上Python+Selenium WebDriver環(huán)境的搭建分為兩個部分:
安裝python
安裝Selenium
標準的安裝步驟
選擇Python的版本。
Python主流的有兩個大的版本,2.7和3.5(請注意,從Python的3.5版本開始,不再支持Windows XP操作系統(tǒng),Windows XP用戶請安裝3.4版本)。我們的例子將會選用面向未來的3.5版本。
安裝Python。
在Python的官網(wǎng)下載最新的安裝包,進行界面安裝。https://www.python.org/
安裝的時候,推薦選擇“Add exe to path”,將會自動添加Python的程序到環(huán)境變量中。然后可以在命令行輸入python -V檢測安裝的Python版本。
當前的版本安裝中將會默認已經(jīng)安裝了setuptools和pip這兩個Python的基本工具。如果使用了比較舊的Python版本的話,需要自行安裝這兩個工具。
setuptools:Python的基礎工具包,用來構建、安裝卸載Python程序
pip:Python軟件包的安裝和管理工具。通過pip可以簡單的安裝Python的任意類庫
安裝Selenium2.0版本。
在Windows安裝Selenium2.0,有兩種途徑。使用pip命令行或者源碼安裝。以下兩種方法,使用任何一個均可。推薦pip的方式。
方法一:pip命令行安裝,運行 | cmd,打開命令行,-U其實就是--upgrade,升級安裝。
pip install -U selenium
方法二:源碼解壓安裝,前往https://pypi.python.org/pypi/selenium下載最新版的PyPI版本的Selenium,解壓后執(zhí)行
python setup.py install
?
Ubuntu下的環(huán)境搭建
在Ubuntu下的Python的解釋器一般情況下已經(jīng)存在了。我們需要打開終端,輸入python -V命令進行驗證。如果沒有安裝Python,那么需要去Python官網(wǎng)上下載指定版本的源文件,進行源碼安裝。安裝完了以后并進行環(huán)境變量的設置。
安裝Selenium WebDriver的方法與上述在Windows環(huán)境下安裝部署的方法一致。依舊推薦使用pip命令行進行安裝。
使用IDE編寫Python
在上述環(huán)境搭建好以后,我們便可使用Python來編寫自動化腳本程序,執(zhí)行Selenium自動化測試。在此之前,我們依舊需要解決一個問題,那就是IDE的選擇。
IDE,Integrated Development Environment,集成開發(fā)環(huán)境。一個好的編輯器或者好的IDE將會極大的提高生產(chǎn)力,幫我們做很多事情,使得編碼工作更加簡單,編碼的體驗更加容易。一般情況下,我們有以下幾種工具可以選擇:
IDLE:Python自帶的IDE,功能簡單,使用方便
Notepad++:一個強大的開源編輯器
Vim:Linux系統(tǒng)中最好用的編輯器之一
Sublime Text:一個非常輕便好用的現(xiàn)代化的編輯器,推薦。
PyCharm:JetBrains公司提供的現(xiàn)代化的跨平臺的Python IDE。
使用Sublime Text 3搭建Python環(huán)境
****通過快捷鍵Ctrl+ 或者View > Show Console打開控制臺,輸入以下代碼并回車
importurllib.request,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())
安裝完以后,重啟Sublime Text 3
如果在Perferences->package settings中看到package control這一項,則安裝成功
按下Ctrl+Shift+P調出命令面板
輸入install package選項并回車
輸入i,匹配到以后,按回車,安裝。Anaconda是一個終極的Python插件。安裝完了以后便可用Sublime Text 3編寫Python代碼,并且使用Ctrl+B來編譯執(zhí)行。
一般來說,一個好的IDE提供一下功能,使你的編碼開發(fā)工作變得更有效率:
一個圖形化的智能代碼提示和補全功能
可以輕松查看方法和類
語法高亮
提供單元測試和調試的工具
源代碼版本管理工具的支持
我們可以嘗試用上述的編輯器或者IDE來進行Python代碼編寫工作。
開始使用WebDriver
接下來我們嘗試幾個簡單的例子來體會一下Selenium WebDriver的使用。
示例1
## 引入WebDriver的包fromseleniumimportwebdriver## 創(chuàng)建瀏覽器對象browser=webdriver.Firefox()## 打開百度網(wǎng)站browser.get('https://www.baidu.com/')
示例2
## 引入WebDriver包fromseleniumimportwebdriver## 引入WebDriver Keys包fromselenium.webdriver.common.keysimportKeys## 創(chuàng)建瀏覽器對象browser=webdriver.Firefox()## 導航到百度主頁browser.get('https://www.baidu.com')## 檢查標題是否為‘百度一下,你就知道’assert'百度一下,你就知道'inbrowser.title## 找到名字為wd的元素,賦值給elemelem=browser.find_element_by_name('wd')# 找到搜索框elem.send_keys('seleniumhq'+Keys.RETURN)# 搜索seleniumhq## 關閉瀏覽器browser.quit()
Selenium 3.0.1 出現(xiàn)的問題以及解決
3.0.1 更新以后,需要做兩個操作:
Geckodriver executable needs to be in PATH。Geckodirver的下載地址:https://github.com/mozilla/geckodriver/releases
報錯內容:
WebDriverException:Message:'geckodriver'executable needs to be in Path
geckodriver是一原生態(tài)的第三方瀏覽器,對于selenium3.x版本都會使用geckodriver來驅動firefox,所以需要下載geckodriver.exe。放置在Path 環(huán)境變量可以訪問到的地方。例如 C:\python34
需要將火狐的安裝路徑放到path,然后重啟(必須重啟電腦)
報錯內容:
selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.
XAMPP的安裝部署和環(huán)境搭建
XAMPP的安裝,在Windows操作系統(tǒng)中比較簡單,可以直接運行安裝文件,默認全部下一步,即可完成軟件的安裝。
請注意:Windows XP系統(tǒng)只能可以XAMPP 1.8.2版本;Windows 7以及以上的系統(tǒng)可以安裝最新版的XAMPP。XAMPP不分32位和64位操作系統(tǒng)。
XAMPP的部署
XAMPP = OS + Apache + MySQL + PHP + Perl
我們一般部署的網(wǎng)站,符合XAMPP環(huán)境的話,只需要啟動Apache和MySQL兩個應用。
部署步驟
啟動Apache
啟動MySQL
解壓網(wǎng)站源文件,例如解壓然之:ranzhi.2.5.zip,請把壓縮包里面的ranzhi這個文件夾解壓出來;禪道也類似,需要把壓縮包中的zentaopms文件夾解壓出來
部署源文件,請將解壓以后的源文件放到xampp\htdocs文件夾中
通過瀏覽器訪問部署好的網(wǎng)站源文件,進行向導安裝。http://localhost/ranzhi/www
PS:這里我們主要支持的是PHP+MySQL開發(fā)的網(wǎng)站部署。
XAMPP的問題解決
無法啟動Apache:請認真查看日志,判斷80和443端口被什么樣的程序占用,需要關閉對應程序,或者修改Apache的端口。
IIS:控制面板 | 管理工具 | Internet信息服務 | 默認網(wǎng)站 | 關閉
VisualSVN Server: 控制面板 | 管理工具 | VisualSVN Server | 關閉
VMware Workstation: 開始 | VMware Workstation | 編輯 | 首選項 | 共享虛擬機 | 禁用共享
HP LoadRunner: 右側任務欄 | 右鍵 | 關閉
修改XAMPP Apache 端口:Config | httpd.conf修改Linsten 80 | Httpd-ssl.conf修改 Listen 443
無法啟動MySQL:請認真查看錯誤日志,找到已經(jīng)啟動的MySQL的程序進程,殺掉該進程。
使用unittest編寫測試腳本
通過上面的例子,我們可以簡單的寫出Selenium WebDriver的腳本,但是對于測試工作來說,上述的腳本還遠遠不夠。因為上述的腳本沒有“檢查”。
接下來我們將會使用Python語言的unittest框架展開“檢查”。
unittest基礎
unittest框架的原本的名字是PyUnit。是從JUnit這樣一個被廣泛使用的Java應用開發(fā)的單元測試框架創(chuàng)造而來。類似的框架還有NUnit(.Net開發(fā)的單元測試框架)等。
我們可以使用unittest框架為任意Python項目編寫可理解的單元測試集合。現(xiàn)在這個unittest已經(jīng)作為Python的標準庫模塊發(fā)布。我們安裝完Python以后,便可以直接使用unittest。
unittest框架提供了編寫test cases,test suites和test fixtures的基本功能。我們首先關注Test cases的編寫與執(zhí)行。
使用unittest需要以下簡單的三步:
引入unittest模組
繼承unittest.TestCase基類
測試方法以test開頭
unittest示例
## 引入unittest模組importunittest## 定義測試類,名字為DemoTests## 該類必須繼承unittest.TestCase基類classDemoTests(unittest.TestCase):## 使用'@'修飾符,注明該方法是類的方法## setUpClass方法是在執(zhí)行測試之前需要先調用的方法## 是開始測試前的初始化工作@classmethoddefsetUpClass(cls):pass## 測試一(務必以test開頭)deftest_01(self):pass## 測試三(務必以test開頭)deftest_02(self):pass## 測試三(務必以test開頭)deftest_03(self):pass## tearDownClass方法是執(zhí)行完所有測試后調用的方法## 是測試結束后的清除工作@classmethoddeftearDownClass(cls):pass# 執(zhí)行測試主函數(shù)if__name__=='__main__':## 執(zhí)行main全局方法,將會執(zhí)行上述所有以test開頭的測試方法unittest.main(verbosity=2)
Python知識的補充:
Python文件的后綴名是.py
.py文件可以用來直接執(zhí)行。也可以被用來作為模塊導入。在cmd命令行中執(zhí)行的命令為python demo.py
在Python中導入模塊(模組)一般使用的是import
使用unittest框架編寫Selenium WebDriver測試
接下來我們查看一個完整的Selenium WebDriver自動化測試實例
實例
importunittestfromseleniumimportwebdriverfromselenium.webdriver.common.keysimportKeysclassSearchTests(unittest.TestCase):defsetUp(self):# 創(chuàng)建一個新的瀏覽器對象self.driver=webdriver.Firefox()self.driver.implicitly_wait(30)self.driver.maximize_window()# 導航到京東主頁self.driver.get("https://www.jd.com/")deftest_search_by_category(self):# 獲取到搜索框self.search_field=self.driver.find_element_by_id("key")self.search_field.clear()# 輸入iphone 6s plus并按下回車進行搜索self.search_field.send_keys("iphone 6s plus"+Keys.RETURN)# 獲取所有的查詢結果products=self.driver.find_elements_by_css_selector("li[class='gl-item']")# 斷言:檢查查詢出來的個數(shù)是否為24個self.assertEqual(24,len(products))deftearDown(self):# 關閉瀏覽器對象self.driver.quit()if__name__=='__main__':unittest.main(verbosity=2)
理解unittest框架提供的各種斷言方法
方法 Method檢查條件
assertEqual(a, b [, msg])a == b,msg可選,用來解釋失敗的原因
assertNotEqual(a, b [, msg]a != b,msg可選,用來解釋失敗的原因
assertTrue(x [, msg])x 是真,msg可選,用來解釋失敗的原因
assertFalse(x [, msg])x 是假,msg可選,用來解釋失敗的原因
assertIsNot(a, b [, msg])a 不是 b,msg可選,用來解釋失敗的原因
WebDriver API 基本操作
這里我們將會開始WebDriver API的基本操作,從元素定位以及瀏覽器的基本操作開始。
定位符
元素的定位和操作是自動化測試的核心部分,其操作是建立在定位的基礎上的。因此我們首選要開始定位元素。
在html里面,元素具有各種各樣的屬性。我們可以通過這樣唯一區(qū)別其他元素的屬性來定位到這個元素。WebDriver提供了一系列的元素定位方法。常見的有以下幾種:
id
name
class name
tag
link text
partial link text
xpath
css selector
查找簡單元素
我們從簡單的一個元素開始定位。最基本的方法是id和name。大多數(shù)元素有這兩個屬性,在對控件的id和name命名是一般也會使其有意義,而取不同的名字。
例如我們看下面這段html
<inputid="search"type="text"name="q"value=""class="input-text"maxlength="128"/>
我們可以使用對應的方法來定位這個input
find_element_by_id('search')find_element_by_name('q')find_element_by_class_name('input-text')
這里我們開始用最簡單的方式來嘗試定位
查看下面一個例子
self.driver.get('http://pro.demo.zentao.net')# 用name定位用戶文本輸入框self.account_field=self.driver.find_element_by_name('account')# 用name定位密碼文本輸入框self.password_field=self.driver.find_element_by_name('password')self.account_field.clear()self.password_field.clear()self.driver.implicitly_wait(30)# 輸入用戶名demoself.account_field.send_keys('demo')# 輸入密碼123456self.password_field.send_keys('123456')self.driver.find_element_by_id('submit').click()self.driver.implicitly_wait(30)companyname=self.driver.find_element_by_id('companyname')self.assertEqual('demo項目管理系統(tǒng)',companyname.text)
示例2
self.driver.find_element_by_id('menuproduct').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menuproject').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menuqa').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menudoc').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menureport').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menucompany').click()self.driver.implicitly_wait(30)self.driver.find_element_by_link_text('退出').click()self.driver.implicitly_wait(30)
此外XPath定位和CSS Selector定位,和定位一組元素這樣的內容案例,將在后續(xù)的講義繼續(xù)探討和講解。
控制瀏覽器
瀏覽器的控制也是自動化測試的一個基本組成部分,我們可以將瀏覽器最大化,設置瀏覽器的高度和寬度以及對瀏覽器進行導航操作等。
## 瀏覽器最大化driver.maximize_window()## 設置瀏覽器的高度為800像素,寬度為480像素driver.set_window_size(480,800)## 瀏覽器后退driver.back()## 瀏覽器前進driver.forward()
這里我們做一個綜合性的練習實例
# coding=utf-8importunittestfromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditions# import sys# reload(sys)# sys.setdefaultencoding('utf8')classWebDriverTests(unittest.TestCase):@classmethoddefsetUpClass(cls):# create a new Firefox sessioncls.driver=webdriver.Firefox()cls.driver.get('about:blank')cls.driver.implicitly_wait(30)print(" -- set up finished -- ")print()deftest_01_navigate(self):passurl_baidu='https://www.baidu.com/'url_zentao='http://pro.demo.zentao.net/user-login-Lw==.html'# 導航到百度self.driver.get(url_baidu)self.driver.maximize_window()self.driver.implicitly_wait(30)# 導航到禪道self.driver.get(url_zentao)self.driver.maximize_window()self.driver.implicitly_wait(30)# 后退self.driver.back()self.assertEqual(url_baidu,self.driver.current_url)self.driver.implicitly_wait(30)# 前進self.driver.forward()self.assertEqual(url_zentao,self.driver.current_url)self.driver.implicitly_wait(30)print("-- test 01 finished -- ")print()deftest_02_element_interaction(self):self.driver.get('http://pro.demo.zentao.net')## 找到用戶名和密碼的輸入框self.account_field=self.driver.find_element_by_name('account')self.password_field=self.driver.find_element_by_name('password')## 清除當前的輸入self.account_field.clear()self.password_field.clear()self.driver.implicitly_wait(30)## 輸入用戶名和密碼,進行登錄self.account_field.send_keys('demo')self.password_field.send_keys('123456')self.driver.find_element_by_id('submit').click()self.driver.implicitly_wait(30)companyname=self.driver.find_element_by_id('companyname')self.assertEqual('demo項目管理系統(tǒng)',companyname.text)print(companyname.get_attribute('type'))print()self.driver.implicitly_wait(30)print('-- test 02 finished -- ')print()deftest_03_element_interation2(self):## 這里執(zhí)行了一段JavaScript代碼js='selectTheme("green")'self.driver.execute_script(js)self.driver.implicitly_wait(30)js='selectTheme("red")'self.driver.execute_script(js)self.driver.implicitly_wait(30)js='selectTheme("lightblue")'self.driver.execute_script(js)self.driver.implicitly_wait(30)js='selectTheme("blackberry")'self.driver.execute_script(js)self.driver.implicitly_wait(30)self.driver.find_element_by_id('menuproduct').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menuproject').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menuqa').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menudoc').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menureport').click()self.driver.implicitly_wait(30)self.driver.find_element_by_id('menucompany').click()self.driver.implicitly_wait(30)self.driver.find_element_by_link_text('退出').click()self.driver.implicitly_wait(30)WebDriverWait(self.driver,10).until(expected_conditions.element_to_be_clickable((By.ID,"submit")))self.driver.implicitly_wait(30)print('-- test 03 finished -- ')print()deftest_04_cookies(self):self.driver.add_cookie({'name':'key-neeeeew','value':'value-neeeewwwww'})# 遍歷cookies 中的name 和value 信息打印,當然還有上面添加的信息forcookieinself.driver.get_cookies():print("%s -> %s"%(cookie['name'],cookie['value']))print()self.driver.delete_all_cookies()cookies=self.driver.get_cookies()print(cookies)print()print('-- test 04 finished -- ')print()@classmethoddeftearDownClass(cls):# close the browser windowcls.driver.quit()passprint('-- tear down finished -- ')print()if__name__=='__main__':unittest.main(verbosity=2)