Selenium 2 自動化測試實(shí)例 更新中...
目錄:
[TOC]
[1. 自動化測試基礎(chǔ)]
[2. 測試環(huán)境搭建]
[3. Python基礎(chǔ)]
[4. WebDriver API]
[5. 自動化測試模型]
[6. selenium IDE]
[7. unittest 單元測試框架]
[8. 自動化測試高級應(yīng)用]
[9. Selenium Grid2]
[10. Python多線程]
[11. 自動化測試實(shí)戰(zhàn)]
[12. BDD框架指Lettuce入門]
[13. GitHub托管項(xiàng)目]
[14. 持續(xù)繼承Jenkins入門]
1. 自動化測試基礎(chǔ)
1.1 軟件測試分類
1. 根據(jù)項(xiàng)目流程階段劃分測試
- 單元測試: 單個(gè)子程序測試
- 集成測試: 模塊由多個(gè)單元集成成子系統(tǒng)再測試
- 系統(tǒng)測試: 針對整個(gè)產(chǎn)品系統(tǒng)的測試
- 驗(yàn)收測試: 部署軟件之前的最后一個(gè)測試階段
2. 白盒測試、黑盒測試、灰盒測試
- 黑盒:只關(guān)心軟件的輸入數(shù)據(jù)和輸出結(jié)果
- 白盒:產(chǎn)品內(nèi)部動作和代碼邏輯是否按照設(shè)計(jì)規(guī)格進(jìn)行
- 灰盒:介于黑盒和白盒之間,既關(guān)注輸入輸出的正確性,同時(shí)也關(guān)注內(nèi)部的表現(xiàn)
3. 功能測試和性能測試
- 功能測試:邏輯功能測試、界面測試、易用性測試、安裝測試、兼容性測試等等
- 性能測試:
- 時(shí)間性能:具體響應(yīng)時(shí)間
- 空間性能:消耗占用系統(tǒng)資源,例如硬件資源,CPU、內(nèi)存、網(wǎng)絡(luò)帶寬消耗等
4. 手工測試與自動化測試
- 手工測試:由測試人員一個(gè)一個(gè)地去執(zhí)行測試用例
- 自動化測試:把人為驅(qū)動的測試行為轉(zhuǎn)化為機(jī)器執(zhí)行的一種過程
- 功能自動化測試:測試工具(或者框架)錄制/編寫測試腳本,對軟件的功能進(jìn)行測試,并驗(yàn)證測試結(jié)果是否正確,從而替代部分手工測試工作,達(dá)到節(jié)約時(shí)間成本、人力成本
- 性能自動化測試:通過性能工具來模擬成千上萬的虛擬用戶向系統(tǒng)發(fā)送請求,具而驗(yàn)證系統(tǒng)的處理能力
5. 冒煙測試、回歸測試、隨機(jī)測試、探索型測試和安全測試
- 冒煙測試:先驗(yàn)證具體的基本功能是否實(shí)現(xiàn),是否具備進(jìn)行大規(guī)模系統(tǒng)測試
- 回歸測試:修改之后的舊代碼,從新測試,檢測有沒有引進(jìn)新的錯(cuò)誤或者導(dǎo)致其他代碼產(chǎn)生錯(cuò)誤
- 隨機(jī)測試:輸入數(shù)據(jù)是隨機(jī)生成的,其目的是模擬用戶的真實(shí)操作,并發(fā)現(xiàn)一些邊緣型的錯(cuò)誤
- 探索性測試:一種測試思維方式,強(qiáng)調(diào)在碰到問題時(shí)及時(shí)改變測試策略
1.2 分層的自動化測試
測試金字塔的概念由敏捷大師 Mike Cohn 在他的 Succeeding with agile 一書中首次提出。
基本觀念是:我們應(yīng)該有更多的低級別的單元測試,而不僅僅是通過用戶界面運(yùn)行的端到端的測試。
所謂傳統(tǒng)的自動化測試我們可以理解為基于產(chǎn)品的UI層的自動化測試,它是將黑盒功能測試轉(zhuǎn)化為由程序或者工具執(zhí)行的一種自動化測試。
UI自動化測試成本維護(hù)高昂,UI易變。
分層自動化測試倡導(dǎo)的是由黑盒(UI)單層到黑白盒多層的自動化測試體系,從全面的黑盒自動化測試到對系統(tǒng)的不同曾次進(jìn)行自動化測試。
- 單元自動化測試
- 是指針對軟件的最小可測試單元進(jìn)行檢查和驗(yàn)證。對于單元測試中的單元的含義,一般來說c語言是指一個(gè)函數(shù),Java是指一個(gè)類,圖形化軟件是一個(gè)窗口或者菜單,需要用到測試框架。
- Java:Junit、TestNG
- C#:NUnit
- python:unittest、pytest
- Code Review 代碼審查
- Java:Eclipse的ReviewClipse和Jupiter
- python:Review Board
- 是指針對軟件的最小可測試單元進(jìn)行檢查和驗(yàn)證。對于單元測試中的單元的含義,一般來說c語言是指一個(gè)函數(shù),Java是指一個(gè)類,圖形化軟件是一個(gè)窗口或者菜單,需要用到測試框架。
- 接口自動化測試
- 模塊接口測試
- 測試模塊之間的調(diào)用與返回,強(qiáng)調(diào)一個(gè)類方法或者函數(shù)的調(diào)用,并對返回結(jié)果的驗(yàn)證,同單元自動化測試
- Web接口測試
- 服務(wù)器接口測試:是指測試瀏覽器與服務(wù)器的接口,通過HTTP協(xié)議實(shí)現(xiàn)前后端的數(shù)據(jù)傳遞測試
- 外部接口測試:指調(diào)用的接口由第三方系統(tǒng)提供,典型例子就是第三方登錄,用戶登錄信息的驗(yàn)證由第三方完成,并返回給當(dāng)前系統(tǒng)是否驗(yàn)證通過
- 當(dāng)然,接口測試也有類庫或者工具,例如測試HTTP的有HttpUnit、Postman等
- 模塊接口測試
- UI自動化測試
- UI測試工具:UFT、Watir、Robot Framework、Selenium
- 前端:QUnit就是針對JavaScript的單元測試工具
《Google測試之道》 一書中提到,測試類型分為大、中、小測試,采用比例1:2:7,大體對應(yīng)UI層、Service、Unit
| UI層 | Service | Unit |
|---|---|---|
| 大 | 中 | 小 |
| 10% | 20% | 70% |
1.3 什么項(xiàng)目適合做自動化測試
- 任務(wù)測試明確,不會頻繁變動
- 每日構(gòu)建后的測試驗(yàn)證
- 比較頻繁的回歸測試
- 軟件系統(tǒng)的界面穩(wěn)定,變動少
- 需要在多平臺上運(yùn)行的測試案例,組合便利型的測試,大量的重復(fù)任務(wù)
- 軟件維護(hù)周期長
- 項(xiàng)目進(jìn)度壓力不算太大
- 被測軟件系統(tǒng)開發(fā)較為規(guī)范,能夠保證系統(tǒng)的可測試性
- 具備大量的自動化測試平臺
- 測試人員較強(qiáng)的變成能力
1.4 市面上常見的自動化測試工具
- UFT:HP開發(fā),QTP與ST合并而來。企業(yè)級自測工具,提供強(qiáng)大醫(yī)用的錄制回放功能,兼容對象識別模式與圖像識別模式兩種識別方式,支持B/S C/S兩種架構(gòu)
- Robot Framework:基于Python編寫的自動化測試框架,可擴(kuò)展,支持關(guān)鍵字,同時(shí)可以測試多種客戶端或者接口,可以分布式測試
- Watir:基于Web模式的自動化功能測試工具。Wair是一個(gè)Ruby語言庫
- Selenium:是一個(gè)Web應(yīng)用程序測試工具,支持多平臺、多瀏覽器、多語言,應(yīng)用廣泛
1.5 Selenium工具介紹
基于Web應(yīng)用程序的自動化測試,但不局限于此,它還支持所有基于web的管理任務(wù)自動化
特點(diǎn):
- 開源免費(fèi)
- 多瀏覽器支持:Firefox、Chrome、IE、Opera、Edge
- 多平臺支持:Linux、windows、Mac
- 多語言:Java、Python、Ruby、JavaScript、C#、C++
- 對web頁面的良好的支持
- 簡單API、靈活(用開發(fā)語言驅(qū)動)
- 支持分布式測試用例
Selenium:
- Selenium IDE:嵌入火狐Firefox的一個(gè)插件,實(shí)現(xiàn)簡單的瀏覽器操作錄制、回放,快速創(chuàng)建bug重現(xiàn)腳本,通過IDE將重現(xiàn)的步驟記錄下來,重現(xiàn)BUG
- Selenium Grid:自動化測試輔助工具,Grid通過利用現(xiàn)有的計(jì)算機(jī)基礎(chǔ)設(shè)施,能加快Web-App的功能測試,利用Grid可以很方便的實(shí)現(xiàn)多臺機(jī)器上和異構(gòu)環(huán)境中測試用例
- Selenium RC:家族的核心部分,通過Selenium RC的服務(wù)器作為代理服務(wù)器去訪問應(yīng)用。Selenium Libraries庫主要用于編寫測試腳本,用來控制Selenium Server庫。Selenium Server負(fù)責(zé)控制瀏覽器行為。
- client
- Server
- Launcher:用于啟動瀏覽器,把Selenium Core加載到瀏覽器頁面當(dāng)中,并把瀏覽器的代理設(shè)置為Selenium Server的Http Proxy
- Http Proxy:代理服務(wù)器(Proxy)是網(wǎng)絡(luò)信息的中轉(zhuǎn)站
- Core:是被Selenium Server嵌入到到瀏覽器的頁面中,其實(shí) Selenium Core就是一堆JavaScript函數(shù)的集合,通過這些JS函數(shù),可以實(shí)現(xiàn)程序?qū)g覽器的操作
Selenium 2.0 = Selenium 1.0 + WebDriver
WebDriver是Selenium RC的替代品,為了保持向下兼容,并沒有完全拋棄 Selenium Core,新的項(xiàng)目可以直接使用WebDriver
- Selenium RC:是在瀏覽器中運(yùn)行JS腳本,使用瀏覽器內(nèi)置的JS的編譯器來翻譯和執(zhí)行selenese(selenese是Selenium命令合集)
- WebDriver:是通過原生瀏覽器支持或者瀏覽器擴(kuò)展來直接控制瀏覽器。WebDriver針對各個(gè)瀏覽器而開發(fā),取代了嵌入到被測Web應(yīng)用中的JavaScript,與瀏覽器緊密集成,因此支持創(chuàng)建更高級的測試,便面的JavaScript安全模型導(dǎo)致的限制,還利用操作系統(tǒng)級別的調(diào)用,模擬用戶輸入??梢岳@過JavaScript沙箱
1.6 前端技術(shù)介紹
- HTML
- JavaScript
- XML
1.7 前端工具介紹
- FireBug
- FirePath:快速檢查和生成XPath1.0表達(dá)式
- Chrome、IE
1.8 開發(fā)語言選擇
本文選擇的是Python
2. 測試環(huán)境搭建
2.1 Windows下的環(huán)境搭建
2.1.1 安裝Python
2.1.2 安裝setuptools與pip
2.1.3 安裝Selenium
2.1.4 ActivePython
- Python專用編程和調(diào)試工具,包含Python內(nèi)核,同時(shí)可以訪問Windows API的所有服務(wù)
- 集成PIP,可以用PIP安裝Selenium庫
2.2 Ubuntu下環(huán)境搭建
2.3 使用IDLE編寫Python
2.4 編寫第一個(gè)自動化腳本
在執(zhí)行程序的時(shí)候,如果遇到錯(cuò)誤代碼是如下樣子:
selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.
則需要下載 geckodriver驅(qū)動文件,放在/usr/local/bin目錄里。
下載網(wǎng)址是:https://github.com/mozilla/geckodriver/releases/
如果是Linux系統(tǒng),下載文件名是:geckodriver-v0.16.1-linux64.tar.gz (最新版本即可)
# coding:utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys("Selenium2")
driver.find_element_by_id("su").click()
sleep(5)
driver.quit()
2.5 安裝瀏覽器驅(qū)動
地址:Selenium - Web Browser Automation
如果打不開,百度搜索相應(yīng)的驅(qū)動。安裝位置,Windows安裝在path環(huán)境變量下,Linux安裝在/usr/local/bin
FireFoxdriver地址
Chromedriver地址
IEdriver地址 需要對應(yīng)你的Selenium版本 windows下 IEDriver相關(guān)設(shè)置
HTMLTestRunner.py地址
sudo apt-get install xvfb
sudo apt-get install unzip
wget -N http://chromedriver.storage.googleapis.com/2.26/chromedriver_linux64.zip
unzip chromedriver_linux64.zip
chmod +x chromedriver
sudo mv -f chromedriver /usr/local/share/chromedriver
sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
sudo ln -s /usr/local/share/chromedriver /usr/bin/chromedriver
selenium官方加上第三方宣布支持的驅(qū)動有很多種;除了PC端的瀏覽器之外,還支持iphone、Android的driver;大概記錄一下selenium支持的各種driver的用途與說明。
selenium可支持的PC瀏覽器驅(qū)動包括:
FF driver【包含在各自語言的客戶端里】
safari driver【包含在selenium server中】
ie driver
chrome driver 【第三方】
opera driver【第三方】
selenium可支持的偽瀏覽器驅(qū)動:
PhantomJS Driver【第三方】
HtmlUnit Driver【包含在selenium server中】
selenium可支持的移動端驅(qū)動:
Windows Phone driver 【第三方】
Selendroid -Selenium for android【第三方】
ios-driver 【第三方】
Appium 支持iphone、ipad、android、FirefoxOS【第三方】
上述的所有驅(qū)動不僅可以直接通過各自語言客戶端來調(diào)用,還是注冊到selenium grid中進(jìn)行分布式的遠(yuǎn)程調(diào)用。
因?yàn)橐苿佣说膁river都沒有嘗試過,所以就不做說明。PC端的driver都是基于瀏覽器的,主要分為2種類型:
一種是真實(shí)的瀏覽器driver
比如:safari、ff都是以插件形式驅(qū)動瀏覽器本身的;ie、chrome都是通過二進(jìn)制文件來驅(qū)動瀏覽器本身的;
這些driver都是直接啟動并通過調(diào)用瀏覽器的底層接口來驅(qū)動瀏覽器的,因此具有最真實(shí)的用戶場景模擬,主要用于進(jìn)行web的兼容性測試使用。
一種是偽瀏覽器driver
selenium支持的偽瀏覽器包括htmlunit、PhantomJS;他們都不是真正的在瀏覽器、都沒有GUI,而是具有支持html、js等解析能力的類瀏覽器程序;這些程序不會渲染出網(wǎng)頁的顯示內(nèi)容,但是支持頁面元素的查找、JS的執(zhí)行等;由于不進(jìn)行css及GUI渲染,所以運(yùn)行效率上會比真實(shí)瀏覽器要快很多,主要用在功能性測試上面。
htmlunit是Java實(shí)現(xiàn)的類瀏覽器程序,包含在selenium server中,無需驅(qū)動,直接實(shí)例化即可;其js的解析引擎是Rhino
PhantomJS是第三方的一個(gè)獨(dú)立類瀏覽器應(yīng)用,可以支持html、js、css等執(zhí)行;其驅(qū)動是Ghost driver在1.9.3版本之后已經(jīng)打包進(jìn)了主程序中,因此只要下載一個(gè)主程序即可;其js的解析引擎是chrome 的V8。
driver類型 優(yōu)點(diǎn) 缺點(diǎn) 應(yīng)用
真實(shí)瀏覽器driver 真實(shí)模擬用戶行為 效率、穩(wěn)定性低 兼容性測試
HtmlUnit 速度快 js引擎不是主流的瀏覽器支持的 包含少量js的頁面測試
PhantomJS 速度中等、模擬行為接近真實(shí) 不能模擬不同/特定瀏覽器的行為 非GUI的功能性測試
PS:除上述的幾種真實(shí)瀏覽器driver中,也可以通過不同的手段來取消瀏覽器的css解析、界面渲染等目的;這樣既可以保證瀏覽器的真實(shí)兼容性、也可以提高執(zhí)行效率問題;使用的手段有:autoit、pyvirtualdisplay、瀏覽器設(shè)置等。
2.6 不同語言使用WebDriver
- 導(dǎo)入selenium(WebDriver)相關(guān)模塊
- 調(diào)用瀏覽器驅(qū)動,獲取瀏覽器句柄,并啟動
- 通過句柄訪問地址百度
- 通過句柄操作頁面元素(百度輸入框和按鈕)
- 通過句柄關(guān)閉瀏覽器
3. Python基礎(chǔ)
3.1 Python哲學(xué)
3.2 輸入輸出
3.3 分支與循環(huán)
3.4 數(shù)組與字典
3.5 函數(shù)、類和方法
3.6 模組、類庫、模塊
當(dāng)多個(gè)模塊之間存在引用,模塊內(nèi)之間文件里的類存在繼承和引用關(guān)系
需要在模塊內(nèi)創(chuàng)建一個(gè)空的init.py文件
當(dāng)一個(gè)模塊調(diào)用另一個(gè)模塊的時(shí)候
用:
import sys
sys.path.append("./model") # (model就是相應(yīng)的被引用模塊)
from model import new_count
4. WebDriver API
4.1 從定位元素開始
WebDriver在Python中一個(gè)有8種方法找到頁面元素:
| 標(biāo)簽 | 定位元素 |
|---|---|
| id | name |
| class name | tag name |
| link text | partial link text |
| xpath | css selector |
| find_element_by_id() | find_element_by_name() |
| find_element_by_class_name() | find_element_by_tag_name() |
| find_element_by_link_text() | find_element_by_partial_link_text() 通過部分文字定位 |
| find_element_by_xpath() | find_element_by_css_selector() |
XPath定位:
絕對路徑定位
find_element_by_xpath("/html/body/div/div[2]/div/div/from/span/input")
利用元素屬性定位:
find_element_by_xpath("http://input[@id='kw']")
find_element_by_xpath("http://input[@name='wd']")
find_element_by_xpath("http://input[@class='s_ipt']")
find_element_by_xpath("http://*[@class='s_ipt']")
find_element_by_xpath("http://input[@maxlength='100']")
find_element_by_xpath("http://input[@autocomplete='off']")
find_element_by_xpath("http://input[@type='submit']")
層級與屬性結(jié)合:
find_element_by_xpath("http://span[@class='bg_s_ipt_wr']/input")
find_element_by_xpath("http://form[@id='form']/span/input")
使用邏輯運(yùn)算符:
find_element_by_xpath("http://input[@id='kw' and @class='su']/span/input")
css定位
通過class屬性定位:
find_element_by_css_selector(".s_ipt")
find_element_by_css_selector(".bg s_btn")
通過id屬性定位:
find_element_by_css_selector("#kw")
find_element_by_css_selector("#su")
通過標(biāo)簽名定位:
find_element_by_css_selector("input")
find_element_by_css_selector("span>input")
通過屬性定位:
find_element_by_css_selector("[autocomplete=off]")
find_element_by_css_selector("[name='kw']")
find_element_by_css_selector("[type='submit']")
組合定位:
find_element_by_css_selector("form.fm>span>input.s_ipt")
find_element_by_css_selector("form.fm>span>input#kw")
用by定位元素
略過。。
4.2 控制瀏覽器
4.3 元素控制
| 命令 | 效果 |
|---|---|
| driver.set_window_size(480,800) | 控制瀏覽器寬400高800 |
| driver.get(url) | 獲取url地址頁面 |
| driver.forward() | 前進(jìn) |
| driver.back() | 后退 |
| driver.quit() | 退出 |
| driver.refresh() | 刷新頁面 |
| driver.find_element_by_css_selector("#id").clear() | 清除文本 |
| driver.find_element_by_css_selector("#id").send_keys("abc") | 模擬按鍵輸入 |
| driver.find_element_by_css_selector("#id").click() | 單擊元素 |
| driver.find_element_by_css_selector("#id").submit() | 提交 |
| size = driver.find_element_by_css_selector("#id").size | 輸入框的尺寸 |
| driver.find_element_by_css_selector("#id").text | 文本 |
| driver.find_element_by_css_selector("#id").get_attribute() | 獲取id、name、type其他任意屬性 |
| driver.find_element_by_css_selector("#id").is_displayed() | 返回元素結(jié)果是否可見 |
4.4 鼠標(biāo)事件
| 命令 | 效果 |
|---|---|
| perform() | 執(zhí)行所有ActionChains中儲存的行為 |
| context_click() | 右擊 |
| double_click() | 雙擊 |
| drag_and_drop() | 拖動 |
| move_to_element() | 鼠標(biāo)懸停 |
# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Firefox()
driver.get("https://www.baidu.com/")
# 定位右擊的元素
right_click = driver.find_element_by_id("su")
# 執(zhí)行右擊操作
ActionChains(driver).context_click(right_click).perform()
# 將瀏覽器句柄driver作為參數(shù),傳入ActionChains行動鏈
# context_click() 鼠標(biāo)右擊操作,需要傳入元素定位
# perform() 可以理解為對所有行動操作列表的提交
# ActionChains(driver).move_to_element(above).perferm() 鼠標(biāo)懸停
# ActionChains(driver).double_click(double_click).perferm() 鼠標(biāo)雙擊
# element, target = driver.find_element_by_id("xx"), driver.find_element_by_id("xx")
# ActionChains(driver).drag_and_drop(element, target).perferm() 鼠標(biāo)拖放
4.5 鍵盤事件
# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
driver = webdriver.Firefox()
driver.get("https://www.baidu.com/")
driver.find_element_by_id("kw").send_keys("seleniumm")
# driver.find_element_by_id("su").click()
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) # 回退 刪除
# driver.find_element_by_id("kw").send_keys(Keys.SPACE) # 添加空格
driver.find_element_by_id("kw").send_keys(u" ") # 添加空格
driver.find_element_by_id("kw").send_keys(u"教程") # 添加文字
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a') # 輸入框全選
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x') # 輸入框剪切
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v') # 輸入框復(fù)制
driver.find_element_by_id("kw").send_keys(Keys.ENTER) # 回車代替單擊
sleep(5)
driver.quit()
| 操作 | 效果 |
|---|---|
| send_keys(Keys.BACK_SPACE) | 刪除 |
| send_keys(Keys.SPACE) | 空格 |
| send_keys(Keys.TAB) | 制表符 |
| send_keys(Keys.ESCAPE) | 回退 |
| send_keys(Keys.ENTER) | 回車 |
| send_keys(Keys.CONTROL, 'a') | 全選 |
| send_keys(Keys.CONTROL, 'c') | 復(fù)制 |
| send_keys(Keys.CONTROL, 'v') | 粘貼 |
| send_keys(Keys.CONTROL, 'x') | 剪切 |
| send_keys(Keys.F1) | 鍵盤F1 |
| send_keys(Keys.F12) | 鍵盤F12 |
常用鍵盤操作:
| 操作 | 效果 |
|---|---|
| send_keys(Keys.BACK_SPACE) | 刪除 |
| send_keys(Keys.SPACE) | 空格 |
| send_keys(Keys.TAB) | 制表符 |
| send_keys(Keys.ESCAPE) | 回退 |
| send_keys(Keys.ENTER) | 回車 |
| send_keys(Keys.CONTROL, 'a') | 全選 |
| send_keys(Keys.CONTROL, 'c') | 復(fù)制 |
| send_keys(Keys.CONTROL, 'v') | 粘貼 |
| send_keys(Keys.CONTROL, 'x') | 剪切 |
| send_keys(Keys.F1) | 鍵盤F1 |
| send_keys(Keys.F12) | 鍵盤F12 |
4.6 獲取驗(yàn)證信息
title = driver.title
now_url = driver.current_url
user = driver.find_element_by_id('spanUid').text
4.7 設(shè)置元素等待
WebDirverWait(driver, 5, 0.5)
WebDirverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
- driver:瀏覽器驅(qū)動
- timeout:超時(shí)時(shí)長
- poll_frequency:間隔時(shí)長
- ignored_exceptions:超時(shí)后的異常信息
# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Firefox()
driver.get("https://www.baidu.com")
element = WebDriverWait(driver, 5, 0.5).until(
EC.presence_of_all_elements_located((By.ID, "kw"))
)
driver.find_element_by_id("kw").send_keys('selenium')
driver.find_element_by_id("kw").send_keys(Keys.ENTER)
# element.send_keys('selenium')
time.sleep(5)
driver.quit()
# until(method, message='') 調(diào)用該方法提供的驅(qū)動程序作為一個(gè)參數(shù),直到返回為True
第二種方法:
隱式等待 implicitly_wait()
# coding:utf-8
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from time import ctime
driver = webdriver.Firefox()
driver.implicitly_wait(10) # 休眠時(shí)間
driver.get("http://www.baidu.com")
try:
print(ctime())
driver.find_element_by_id("kw22").send_keys('selenium')
except NoSuchElementException as e:
print(e)
finally:
print(ctime())
driver.quit()
第三種方法:
sleep
from time import sleep
sleep(10)
4.8 復(fù)選
# coding:utf-8
from selenium import webdriver
import os, time
driver = webdriver.Firefox()
file_path = 'file:///' + os.path.abspath('checkbox.html') # abspath()返回絕對路徑
driver.get(file_path)
# inputs = driver.find_element_by_tag_name('input')
#
# for i in inputs:
# if i.get_attribute('type') == 'checkbox':
# i.click()
# time.sleep(1)
# checkboxs = driver.find_elements_by_xpath("http://input[@type='checkbox']")
checkboxs = driver.find_elements_by_css_selector("input[type=checkbox]")
for checkbox in checkboxs:
checkbox.click()
time.sleep(1)
driver.find_elements_by_css_selector('input[type=checkbox]').pop().click() # 去掉最后一個(gè)
# pop(0) 第一個(gè)
# pop(-1) 最后一個(gè)
# pop(1) 第二個(gè)
driver.quit()
4.9 多表單切換
driver.switch_to.frame("if") # 切換到id = if的frame框架,frame()可以去id或者name屬性 或者
xf = driver.find_element_by_xpath("http://*[@class='if']")
driver.switch_to.frame(xf)
switch_to.default_content() # 跳到最外層表單
4.10 多窗口切換
# coding:utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
# 獲得百度搜索窗口句柄
sreach_windows = driver.current_window_handle
# a.lb:nth-child(7)
# html body div#wrapper div#head div.head_wrapper div#u1 a.lb
# a_links = driver.find_element_by_css_selector("a.lb:nth-child(7)")
# print a_links.text
# links = driver.find_elements_by_link_text('登錄')
# print links
driver.find_elements_by_link_text('登錄').pop().click()
driver.find_element_by_link_text("立即注冊").click()
# driver.find_element_by_link_text('登錄').click()
# driver.find_element_by_link_text("立即注冊").click()
# 獲得當(dāng)前所有打開的窗口的句柄
all_handles = driver.window_handles
# 進(jìn)入注冊窗口
for handle in all_handles:
if handle != sreach_windows:
driver.switch_to.window(handle)
print 'now register window!'
driver.find_element_by_name("account").send_keys('username')
driver.find_element_by_name("password").send_keys('password')
time.sleep(2)
# 回到搜索窗口
for handle in all_handles:
if handle == sreach_windows:
print 'now sreach window'
driver.find_element_by_id('TANGRAM__PSP_2__closeBtn').click()
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
print driver.current_window_handle
time.sleep(5)
driver.quit()
4.11 警告框處理
| 命令 | 效果 |
|---|---|
| text | 返回alert/confirm/prompt中的文字 |
| accpet() | 接受現(xiàn)有警告框 |
| dismiss() | 解散現(xiàn)有警告框 |
| send_keys(keysToSend) | 發(fā)送文本至警告框 keysToSend:將文本發(fā)送至警告框 |
| switch_to_alert() | 方法接受彈出來的窗口 |
switch_to_alert()方法 定位到 alert/confirm/prompt
text/accept/dismiss/send_keys等方法進(jìn)行操作
| 命令 | 效果 |
|---|---|
| text | 返回alert/confirm/prompt中的文字 |
| accpet() | 接受現(xiàn)有警告框 |
| dismiss() | 解散現(xiàn)有警告框 |
| send_keys(keysToSend) | 發(fā)送文本至警告框 keysToSend:將文本發(fā)送至警告框 |
| switch_to_alert() | 方法接受彈出來的窗口 |
# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
# 鼠標(biāo)懸停至“設(shè)置”鏈接
# link = driver.find_element_by_link_text('設(shè)置')
link = driver.find_elements_by_link_text('設(shè)置').pop()
ActionChains(driver).move_to_element(link).perform()
# 打開搜索設(shè)置
# time.sleep(5)
# print driver.find_element_by_link_text('搜索設(shè)置')
driver.find_element_by_link_text('搜索設(shè)置').click()
js = "var q=document.getElementsByClassName(\"bdlayer pfpanel\");q.style=\"display: block; top: 0px; opacity: 1;\""
driver.execute_script(js)
time.sleep(3)
# res = driver.find_element_by_css_selector(".bdlayer.pfpanel")
# print res
# print res.is_displayed()
# 設(shè)置
driver.find_element_by_css_selector("#sh_1").click()
# 保存設(shè)置
# driver.find_element_by_class_name("prefpanelgo").click()
driver.find_element_by_css_selector(".prefpanelgo").click()
# driver.find_element_by_link_text('恢復(fù)默認(rèn)').click()
time.sleep(2)
# 接受警告框
driver.switch_to_alert().accept()
driver.quit()
4.12
4.12.1 send_keys實(shí)現(xiàn)上傳
找到對應(yīng)的input標(biāo)簽,直接send_keys(文件),傳入對應(yīng)文件
# coding:utf-8
from selenium import webdriver
import os
driver = webdriver.Firefox()
driver.implicitly_wait(5)
file_path = 'file:///' + os.path.abspath('upfile.html')
driver.get(file_path)
# 定位上傳的input,添加本地文件
driver.find_element_by_name('file').send_keys('D:\\upload_file.txt')
driver.quit()
4.12.2 AutoIt實(shí)現(xiàn)上傳
官方下載地址:http://www.aotuitscript.com/site/
windows GUI(圖形用戶界面)自動化測試
| 功能 | 作用 |
|---|---|
| AutoIt Windows Info | 用于識別Windows控件信息 |
| Compile Script to.exe | 用于將AutoIt生成exe執(zhí)行文件 |
| Run Script | 用于執(zhí)行AutoIt腳本 |
| SciTE Script Editor | 用于編寫AutoIt腳本 |
4.13 下載文件
WebDriver允許我們設(shè)置默認(rèn)的文件下載路徑,也就是說,文件會自動下載并且存放到設(shè)置的目錄中。
HTTP Content-type 常用對照表:http://tool.oschina.net/commons
curl -I 可以查看Content-type的值
# coding:utf-8
from selenium import webdriver
import os
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList", 2) # 設(shè)置成0代表保存在默認(rèn)的瀏覽器下載目錄,設(shè)置2代表保存在指定的目錄
fp.set_preference("browser.download.manager.showWhenStarting", False) # 是否顯示開始 True為顯示,F(xiàn)alse為不顯示
fp.set_preference("browser.download.dir", '/home/wy/')
# fp.set_preference("browser.download.dir", os.getcwd()) # 設(shè)置下載目錄 os.getcwd()當(dāng)前的目錄
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream") # 下載文件的類型 指定要下載頁面的Content-type值,‘a(chǎn)pplication/octet-stream’為文件類型
driver = webdriver.Firefox(firefox_profile=fp)
driver.get("https://pypi.python.org/pypi/selenium#downloads")
# driver.find_element_by_css_selector(".button.green").click()
# driver.find_element_by_partial_link_text("selenium-2").click()
driver.find_element_by_css_selector(".even>td>span>a").click()
driver.quit()
Chrome瀏覽器類似,設(shè)置其options:
download.default_directory:設(shè)置下載路徑
profile.default_content_settings.popups:設(shè)置為 0 禁止彈出窗口
它的設(shè)置就簡單多了,看個(gè)示例:
# -*- coding: utf-8 -*-
from selenium import webdriver
from time import sleep
options = webdriver.ChromeOptions()
prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': 'd:\\'}
options.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome(executable_path='D:\\chromedriver.exe', chrome_options=options)
driver.get('http://sahitest.com/demo/saveAs.htm')
driver.find_element_by_xpath('//a[text()="testsaveas.zip"]').click()
sleep(3)
driver.quit()
4.14 操作Cookie
| 操作 | 效果 |
|---|---|
| get_cookies() | 獲得所有cookie信息 |
| get_cookie(name) | 返回字典的key為"name"的cookie信息 |
| add_cookie(cookie_dict) | 添加cookie ‘cookie_dict’指字典對象,必須有name和value值 |
| delete_cookie(name,optionsString) | 刪除cookie信息 “name”是要刪除的cookie的名稱,“optionsString”是該cookie的選項(xiàng),目前支持的選項(xiàng)包括“路徑”,“域” |
| delete_all_cookies() | 刪除所有cookie信息 |
# coding:utf-8
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(3)
# 添加cookie
driver.add_cookie({'name': 'key-aaa', 'value': 'key-bbb'})
driver.get("http://www.youdao.com")
# 獲得cookie信息
cookies = driver.get_cookies()
print cookies
for cookie in cookies:
print cookie['name'], '->', cookie['value']
driver.quit()
4.15 調(diào)用JavaScript
# coding:utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
# 設(shè)置瀏覽器窗口大小
driver.set_window_size(600, 600)
# 搜索
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
sleep(2)
# 通過JS設(shè)置瀏覽器窗口的滾動條位置
js = "window.scrollTo(100,450)"
driver.execute_script(js)
sleep(3)
driver.quit()
4.16 處理HTML5的視頻播放
# coding:utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.implicitly_wait(5)
driver.get("http://videojs.com/")
video = driver.find_element_by_xpath(".//*[@id='preview-player_html5_api']")
# video = driver.find_element_by_xpath("body/Section[1]/div/video")
# 返回播放文件地址
url = driver.execute_script("return arguments[0].currentSrc;", video)
print url
# 播放視頻
print "start"
driver.execute_script("return arguments[0].play()", video)
sleep(15)
# 暫停視頻
print "pause"
driver.execute_script("arguments[0].pause()", video)
driver.quit()
4.17 窗口截圖
# coding:utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get('http://www.baidu.com')
driver.find_element_by_id('kw').send_keys('selenium')
driver.find_element_by_id('su').click()
sleep(2)
# 截取當(dāng)前窗口,并指定截圖保存位置
driver.get_screenshot_as_file("/home/wy/")
driver.quit()
4.18 關(guān)閉窗口
driver.close()
4.19 驗(yàn)證碼的處理
- 叫開發(fā)人員去掉驗(yàn)證碼
- 設(shè)置萬能驗(yàn)證碼
- Python-tesseract光學(xué)識別 Tesseract OCR引擎的封裝類
- 記錄 cookie 繞過驗(yàn)證碼
# ...
# 訪問某網(wǎng)站...
driver.get("http://xxx.com")
driver.add_cookie({'name':'Login_UserNumber','value':'username'})
driver.add_cookie({'name':'Login_Password','value':'password'})
4.20 WebDriver原理
- WebDriver啟動瀏覽器,綁定指定端口,作為Remote Server
- Client 通過CommandExcuter發(fā)送HTTPRequest給Remote Server幀聽端口
- Remote Server需要依賴原聲的瀏覽器組件 轉(zhuǎn)化瀏覽器的native調(diào)用
接收客戶端DEBUG
# coding:utf-8
from selenium import webdriver
import logging
logging.basicConfig(level=logging.DEBUG)
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
driver.quit()
5. 自動化測試模型
測試模型:
- 線性測試
- 模塊化驅(qū)動測試
- 數(shù)據(jù)驅(qū)動測試
- 關(guān)鍵字測試
5.1 自動化測試模型介紹
5.1.1 線性測試
通過錄制或編寫對應(yīng)用程序的操作步驟產(chǎn)生相應(yīng)的線性腳本,每個(gè)測試腳本相對獨(dú)立,且不產(chǎn)生其他依賴與調(diào)用,這是早期的自動化測試的形式,
單純的模擬用戶完整的操作場景,優(yōu)勢完整獨(dú)立,缺點(diǎn)開發(fā)和維護(hù)的成本很高
5.1.2 模塊化測試
把重復(fù)的操作獨(dú)立成公共模塊,當(dāng)用例執(zhí)行過程中用到這一個(gè)模塊時(shí),則被調(diào)用,最大限度的消除了重復(fù),提高可維護(hù)性
5.1.3 數(shù)據(jù)驅(qū)動測試
數(shù)據(jù)驅(qū)動說的直白一點(diǎn)就是數(shù)據(jù)的參數(shù)化,因?yàn)檩斎霐?shù)據(jù)的不同而引起不同的輸出結(jié)果 Datapool
5.1.4 關(guān)鍵字驅(qū)動
無法是把"數(shù)據(jù)"換成"關(guān)鍵字",通過關(guān)鍵字的改變引起測試結(jié)果的改變
目前市面上的典型關(guān)鍵字驅(qū)動工具 QTP(目前已更名UFT-Unified Functional Testing)、Robot Framework(RIDE)工具為主
這類工具封裝了底層的代碼,提供用戶獨(dú)立的圖形界面,以"填表格"的形式免除測試人員對寫代碼的恐懼,從而減低編寫難度
6. selenium IDE
不用翻墻的 安裝地址:https://addons.mozilla.org/en-US/firefox/addon/selenium-ide/
7. unittest 單元測試框架
8. 自動化測試高級應(yīng)用
9. Selenium Grid2
10. Python多線程
11. 自動化測試實(shí)戰(zhàn)
- mztestpro/目錄
- bbs/ 論壇項(xiàng)目
- data/ 存放測試數(shù)據(jù)
- report/ 用于存放HTML測試報(bào)告
- image/ 創(chuàng)建了image目錄用于存放測試過程中的截圖
- test_case/ 測試用例目錄,用于存放測試用例及相關(guān)模塊
- models/ 該目錄下存放了一些公共的配置函數(shù)及公共類
- driver.py
- function.py
- myunit.py
- page_obj/ 該目錄用于存放測試用例的頁面對象(Page Object),根據(jù)自定義規(guī)則,以“*Page.py”命名的文件為封裝的頁面對象文件
- *Page.py
- _sta.py 測試用例文件。根據(jù)測試文件匹配規(guī)則,”_sta.py“命名的文件將被當(dāng)作自動化測試用例執(zhí)行
- models/ 該目錄下存放了一些公共的配置函數(shù)及公共類
- driver/
- package/
- run_bbs_test.py
- startup.bat
- 自動化測試項(xiàng)目說明文檔.md
- bbs/ 論壇項(xiàng)目