閱在線 AIP 文檔:
http://selenium.googlecode.com/git/docs/api/py/index.html
目錄
1、selenium+python 環境搭建................................................................................................6
1.1 selenium 介紹............................................................................................................... 6
1.2 準備工做......................................................................................................................6
1.3 安裝步驟......................................................................................................................7
1.4 安裝chrome driver......................................................................................................8
1.5 安裝 IE driver................................................................................9
2、開始第一個腳本.................................................................................................................9
2.1 爲何選python..........................................................................................................9
2.2 第一個腳本..................................................................................................................9
2.3 腳本解析....................................................................................................................10
3、元素的定位.......................................................................................................................11
3.1 id 和 name 定位.......................................................................................................12
3.2 tagname 和 class name定位...................................................................................12
3.3 CSS 定位..................................................................................................................13
3.4 XPath 定位...............................................................................................................14
3.5 link 定位...................................................................................................................15
3.6 Partial link text 定位................................................................................................15
4、添加等待時間...................................................................................................................15
4.一、添加休眠..................................................................................................................15
4.二、智能等待..................................................................................................................16
5、打印信息...........................................................................................................................17
5.一、打印 tile....................................................................................................................17
5.二、打印 URL.................................................................................................................17
6、瀏覽器的操做...................................................................................................................18
6.一、瀏覽器最大化..........................................................................................................18
6.二、設置瀏覽器寬、高..................................................................................................19
7、操做瀏覽器的前進、後退...............................................................................................19
8、操做測試對象...................................................................................................................20
8.一、鼠標點擊與鍵盤輸入..............................................................................................21
8.二、submit 提交表單......................................................................................................21
8.三、text獲取元素文本...................................................................................................22
8.四、get_attribute 得到屬性值........................................................................................ 22
9、鍵盤事件...........................................................................................................................23
9.一、鍵盤按鍵用法..........................................................................................................23
9.二、鍵盤組合鍵用法......................................................................................................24
9.三、中文亂碼問題..........................................................................................................25
10、鼠標事件...........................................................................................................................25
10.一、鼠標右鍵................................................................................................................26
博客園 — 蟲師
http://fnng.cnblogs.com 4
10.二、鼠標雙擊................................................................................................................27
10.三、鼠標拖放................................................................................................................27
11、定位一組元素...............................................................................................................28
11.一、第一種定位方法....................................................................................................30
11.二、第二種定位方法....................................................................................................31
11.三、去掉最後一個勾選................................................................................................31
12、多層框架/窗口定位......................................................................................................32
12.一、多層框架定位........................................................................................................32
12.二、多層窗口定位........................................................................................................35
十3、層級定位.......................................................................................................................35
十4、上傳文件操做...............................................................................................................38
14.一、操做文件上傳例子................................................................................................39
14.二、139 郵箱上傳.........................................................................................................40
十5、下拉框處理...................................................................................................................41
15.一、操做下拉框例子....................................................................................................41
15.二、百度搜索設置下拉框操做....................................................................................43
十6、alert、confirm、prompt 的處理..................................................................................44
十7、對話框的處理...............................................................................................................45
17.一、div 對話框的處理..................................................................................................45
17.二、通常對話框的處理................................................................................................48
十8、調用 js...........................................................................................................................49
18.一、經過 js 隱藏元素...................................................................................................49
18.二、經過 js 使輸入框標紅...........................................................................................51
十9、控制瀏覽器滾動條.......................................................................................................52
19.一、場景一....................................................................................................................53
19.二、場景二....................................................................................................................53
二10、cookie 處理...................................................................................................................54
20.一、打印 cookie 信息...................................................................................................54
20.二、對cookie 操做.......................................................................................................55
20.三、博客園登錄分析cookie........................................................................................56
二11、webdriver 原理解析................................................................................................. 57
二12、引入 unittest 框架.....................................................................................................65
二十3、unittest 單元測試框架解析......................................................................................70
二十4、批量執行測試集.......................................................................................................75
二十5、異常捕捉與錯誤截圖...............................................................................................77
二十6、生成測試報告(HTMLTestRunner).......................................................................... 80
二十7、數據驅動測試...........................................................................................................83
27.一、讀取文件參數化....................................................................................................83
27.二、用戶名密碼的參數化(讀取文件)................................................................... 85
27.三、用戶名的參數化(字典)....................................................................................86
27.四、用戶名密碼的參數化(函數)........................................................................... 87
二十8、測試套件...................................................................................................................89
28.一、測試套件實例........................................................................................................89
28.二、整合 HTMLTestRunner 測試報告........................................................................93
博客園 — 蟲師
http://fnng.cnblogs.com 5
28.三、更易讀的報告........................................................................................................95
二十9、結構改進...................................................................................................................96
29.一、all_tests.py 移出來................................................................................................96
29.二、__init__.py 文件解析............................................................................................97
29.三、調用多級目錄的用例............................................................................................98
29.四、改進用例的讀取....................................................................................................99
29.五、進一步分離用例列表..........................................................................................101
三10、UliPad--python 開發利器...........................................................................................103
1、selenium+python 環境搭建
1.1selenium 介紹
selenium 是一個 web 的自動化測試工具,很多學習功能自動化的同窗開始首選 selenium ,
相由於它相比 QTP有諸多有點:
* 免費,也不用再爲破解 QTP 而大傷腦筋
* 小巧,對於不一樣的語言它只是一個包而已,而 QTP 須要下載安裝1個多 G 的程序。
* 這也是最重要的一點,無論你之前更熟悉 C、 java、ruby、python、或都是 C# ,你都
能夠經過 selenium 完成自動化測試,而 QTP 只支持 VBS
* 支持多平臺:windows、linux、MAC ,支持多瀏覽器:ie、ff、safari、opera、chrome
* 支持分佈式測試用例的執行,能夠把測試用例分佈到不一樣的測試機器的執行,至關於分
發機的功能。
1.2 準備工做
搭建平臺 windows
準備工具以下:
-------------------------------------------------------------
下載 python
http://python.org/getit/
下載 setuptools 【python的基礎包工具】
http://pypi.python.org/pypi/setuptools
下載 pip 【python 的安裝包管理工具】
https://pypi.python.org/pypi/pip
-------------------------------------------------------------
由於版本都在更新,pyhton 選擇2.7.xx ,setuptools 選擇你平臺對應的版本,pip 不要
擔憂 tar.gz 在 windows 下同樣可用。
1.3 安裝步驟
1、python 的安裝 ,這個不解釋,exe 文件運行安裝便可,既然你選擇 python,相信
你是熟悉 python 的,我安裝目錄 C:\Python27
2、setuptools 的安裝也很是簡單,一樣是 exe 文件,默認會找到 python 的安裝路徑,
將安裝到 C:\Python27\Lib\site-packages 目錄下
3、安裝 pip ,我默認解壓在了 C:\pip-1.3.1 目錄下
4、打開命令提示符(開始---cmd 回車)進入 C:\pip-1.3.1目錄下輸入:
C:\pip-1.3.1 >python setup.pyinstall
(若是提示 python 不是內部或外部命令!別急,去配置一下環境變量吧)
修改個人電腦->屬性->高級->環境變量->系統變量中的 PATH 爲:
變量名:PATH
變量值:;C:\Python27
5、再切換到 C:\Python27\Scripts 目錄下輸入:
C:\Python27\Scripts> easy_install pip
6、安裝 selenium,(下載地址: https://pypi.python.org/pypi/selenium )
若是是聯網狀態的話,能夠直接在 C:\Python27\Scripts 下輸入命令安裝:
C:\Python27\Scripts> pip install -U selenium
若是沒聯網(這個通常不太可能),下載 selenium 2.33.0 (目前的最新版本)
並解壓把整個目錄放到 C:\Python27\Lib\site-packages 目錄下。
注意:7、八兩步能夠暫不進行,若是你要學習第二十一章 webdriver 原理的時候再進行
也不遲。
==============
7、下載並安裝
(http://www.java.com/zh_CN/download/chrome.jsp?locale=zh_CN),什麼!?你沒整過
java 虛擬機,百度一下 java 環境搭建吧。
8、下載 selenium 的服務端(https://code.google.com/p/selenium/)在頁面的左
側列表中找到
selenium-server-standalone-XXX.jar
對!就是這個東西,把它下載下來並解壓;
在 selenium-server-standalone-xxx.jar 目 錄 下 使 用 命 令 java -jar
selenium-server-standalone-xxx.jar 啓動(若是打不開,查看是否端口被佔用:netstat
-aon|findstr 4444)。
==============
1.4 安裝 chrome driver
chrome driver 的下載地址在這裏。
1. 下載解壓,你會獲得一個 chromedriver.exe 文件(我點開,運行提示 started no prot
9515 ,這是幹嗎的?端口9515被佔了?中間折騰了半天),後來才知道須要把這傢伙放到
chrome 的安裝目錄下...\Google\Chrome\Application\ ,而後設置 path 環境變量,把
chrome 的安裝目錄(個人:C:\Program Files\Google\Chrome\Application),而後再調用
運行:
# coding = utf-8
fromselenium import webdriver
driver =webdriver.Chrome()
driver.get('http://radar.kuaibo.com')
print driver.title
driver.quit()
報錯提示:
Chrome version must be >= 27.0.1453.0\n (Driver info:
chromedriver=2.0,platform=Windows NT 5.1 SP3 x86)
說我 chrome 的版本沒有大於27.0.1453.0 ,這個好辦,更新到最新版本便可。
博客園 — 蟲師
http://fnng.cnblogs.com 9
1.5 安裝IE driver
在新版本的 webdriver中,只有安裝了 ie driver使用 ie 進行測試工做。
ie driver 的下載地址在這裏,記得根據本身機器的操做系統版原本下載相應的 driver。
暫時還沒嘗試,應該和 chrome 的安裝方式相似。
記得配置 IE 的保護模式
若是要使用 webdriver啓動 IE 的話,那麼就須要配置 IE 的保護模式了。
把 IE 裏的保護模式都選上或都勾掉就能夠了。
2、開始第一個腳本
2.1 爲何選 python
以前的菜鳥系列是基於 java 的,一年沒學其實也忘的差很少了,目前所測的產品
部分也是 python 寫的,並且團隊也在推廣 python ,其實就測試人員來講,python 也
至關受歡迎。易學,易用。翻翻各測試招聘,python 出現的機率也頗高。(我的緣由)
最重要的仍是 python 簡單易學,應用也相對普遍;是測試人員學習編程的不二之選。
下面看看 python 穿上 seleniumwebdriver 是多麼的性感:
2.2 第一個腳本
#coding = utf-8
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("http://www.baidu.com")
browser.find_element_by_id("kw" ).send_keys( "selenium")
browser.find_element_by_id("su").click()
博客園 — 蟲師
http://fnng.cnblogs.com 10
browser.quit()
2.3 腳本解析
# coding = utf-8
可加可不加,開發人員喜歡加一下,防止亂碼嘛。
from selenium import webdriver
要想使用 selenium 的 webdriver裏的函數,首先把包導進來嘛
browser = webdriver.Firefox()
咱們須要操控哪一個瀏覽器呢?Firefox ,固然也能夠換成 Ie 或 Chrome 。browser 能夠
隨便取,但後面要用它操縱各類函數執行。
browser.find_element_by_id("kw").send_keys("selenium")
一個控件有若干屬性 id 、name、(也能夠用其它方式定位),百度輸入框的 id 叫 kw ,
我要在輸入框裏輸入 selenium 。多天然語言呀!
browser.find_element_by_id("su").click()
搜索的按鈕的 id 叫 su ,我須要點一下按鈕( click() )。
browser.quit()
退出並關閉窗口的每個相關的驅動程序,有潔癖用這個。
browser.close()
關閉當前窗口 ,用哪一個看你的需求了。
博客園 — 蟲師
http://fnng.cnblogs.com 11
3、元素的定位
對象的定位應該是自動化測試的核心,要想操做一個對象,首先應該識別這個對象。
一個對象就是一我的同樣,他會有各類的特徵(屬性),如比咱們能夠經過一我的的身
份證號,姓名,或者他住在哪一個街道、樓層、門牌找到這我的。
那麼一個對象也有相似的屬性,咱們能夠經過這個屬性找到這對象。
webdriver 提供了一系列的對象定位方法,經常使用的有如下幾種
· id
· name
· class name
· link text
· partial link text
· tag name
· xpath
· css selector
咱們能夠看到,一個百度的輸入框,能夠用這麼用種方式去定位。
<input id="kw" class="s_ipt" type="text" maxlength="100" name="wd"
autocomplete="off">
#coding=utf-8
fromselenium import webdriver
browser =webdriver.Firefox()
browser.get("http://www.baidu.com")
#########百度輸入框的定位方式##########
#經過 id 方式定位
browser.find_element_by_id("kw").send_keys("selenium")
#經過 name 方式定位
browser.find_element_by_name("wd").send_keys("selenium")
#經過 tag name 方式定位
browser.find_element_by_tag_name("input").send_keys("selenium")
#經過 class name 方式定位
browser.find_element_by_class_name("s_ipt").send_keys("selenium")
博客園 — 蟲師
http://fnng.cnblogs.com 12
#經過 CSS 方式定位
browser.find_element_by_css_selector("#kw").send_keys("selenium")
#經過 xphan 方式定位
browser.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")
############################################
browser.find_element_by_id("su").click()
time.sleep(3)
browser.quit()
3.1 id 和 和 name 定位
id 和 name 是咱們最最經常使用的定位方式,由於大多數控件都有這兩個屬性,並且
在對控件的 id 和 name 命名時通常使其有意義也會取不一樣的名字。經過這兩個屬性使我
們找一個頁面上的屬性變得至關容易
咱們經過前端工具,找到了百度輸入框的屬性信息,以下:
<input id="kw" class="s_ipt" type="text" maxlength="100" name="wd"
autocomplete="off">
id=」kw」
經過 find_element_by_id("kw") 函數就是捕獲到百度輸入框
name=」wd」
經過 find_element_by_name("wd")函數一樣也能夠捕獲百度輸入框
3.2 tag name 和 和 class name 定位
從上面的百度輸入框的屬性信息中,咱們看到,不僅僅只有 id 和 name 兩個屬性,
好比 class 和 tag name(標籤名)
<input id="kw" class="s_ipt" type="text" maxlength="100" name="wd"
autocomplete="off">
<input>
博客園 — 蟲師
http://fnng.cnblogs.com 13
input就是一個標籤的名字,能夠經過 find_element_by_tag_name("input") 函數來定
位。
class="s_ipt"
經過 find_element_by_class_name("s_ipt")函數捕獲百度輸入框。
3.3 CSS 定位
CSS(Cascading Style Sheets)是一種語言,它被用來描述 HTML 和 XML 文檔的表現。
CSS 使用選擇器來爲頁面元素綁定屬性。這些選擇器能夠被 selenium 用做另外的定位策
略。
CSS 的比較靈活能夠選擇控件的任意屬性,上面的例子中:
find_element_by_css_selector("#kw")
經過 find_element_by_css_selector( )函數,選擇取百度輸入框的id 屬性來定義
也能夠取 name 屬性
<a href="http://news.baidu.com" name="tj_news">新 聞</a>
driver.find_element_by_css_selector("a[name=\"tj_news\"]").click()
能夠取 title屬性
<a onclick="queryTab(this);" mon="col=502&pn=0" title="web"
href="http://www.baidu.com/">網頁</a>
driver.find_element_by_css_selector("a[title=\"web\"]").click()
也能夠是取..:
<a class="RecycleBin xz" href="javascript:void(0);">
driver.find_element_by_css_selector("a.RecycleBin").click()
雖然我也沒所有理解 CSS 的定位,可是看上去應該是一種很是靈活和牛 X 的定位方式
擴展閱讀:
http://www.w3.org/TR/css3-selectors/
博客園 — 蟲師
http://fnng.cnblogs.com 14
http://www.w3school.com.cn/css/css_positioning.asp
3.4 XPath 定位
什麼是 XPath:http://www.w3.org/TR/xpath/
XPath 基礎教程:http://www.w3schools.com/xpath/default.asp
selenium 中被誤解的 XPath : http://magustest.com/blog/category/webdriver/
XPath 是一種在 XML 文檔中定位元素的語言。由於 HTML 能夠看作 XML 的一種實現,
因此 selenium 用戶但是使用這種強大語言在 web 應用中定位元素。
XPath 擴展了上面 id和 name 定位方式,提供了不少種可能性,好比定位頁面上的
第三個多選框。
xpath:attributer (屬性)
driver.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")
#input 標籤下 id =kw 的元素
xpath:idRelative (id 相關性)
driver.find_element_by_xpath("//div[@id='fm']/form/span/input").send_keys("s
elenium")
#在/form/span/input 層級標籤下有個 div標籤的 id=fm 的元素
driver.find_element_by_xpath("//tr[@id='check']/td[2]").click()
# id 爲'check' 的 tr ,定位它裏面的第2個 td
xpath:position (位置)
driver.find_element_by_xpath("//input").send_keys("selenium")
driver.find_element_by_xpath("//tr[7]/td[2]").click()
#第7個 tr 裏面的第2個td
xpath: href (水平參考)
driver.find_element_by_xpath("//a[contains(text(),'網頁')]").click()
#在 a 標籤下有個文本(text)包含(contains)'網頁' 的元素
xpath:link
driver.find_element_by_xpath("//a[@href='http://www.baidu.com/']").click()
#有個叫 a 的標籤,他有個連接 href='http://www.baidu.com/ 的元素
博客園 — 蟲師
http://fnng.cnblogs.com 15
3.5 link 定位
有時候不是一個輸入框也不是一個按鈕,而是一個文字連接,咱們能夠經過 link
#coding=utf-8
fromselenium import webdriver
browser =webdriver.Firefox()
browser.get("http://www.baidu.com")
browser.find_element_by_link_text("貼 吧").click()
browser.quit()
通常一個頁面上不會出現相同的文件連接,經過文字連接來定位也是一種簡單有效
的定位方式。
3.6 Partiallink text 定位
經過部分連接定位,這個有時候也會用到,我尚未想到很好的用處。拿上面的例
子,我能夠只用連接的一部分文字進行匹配:
browser.find_element_by_partial_link_text("貼").click()
#經過 find_element_by_partial_link_text() 函數,我只用了「貼」字,腳本同樣找到了"貼 吧
" 的連接
4、添加等待時間
有時候爲了保證腳本運行的穩定性,須要腳本中添加等待時間。
4.1 、添加休眠
添加休眠很是簡單,咱們須要引入 time 包,就能夠在腳本中自由的添加休眠時間了。
# coding = utf-8
博客園 — 蟲師
http://fnng.cnblogs.com 16
fromselenium import webdriver
import time #調入 time 函數
browser =webdriver.Firefox()
browser.get("http://www.baidu.com")
time.sleep(0.3) #休眠0.3秒
browser.find_element_by_id("kw").send_keys("selenium")
browser.find_element_by_id("su").click()
time.sleep(3) # 休眠3秒
browser.quit()
4.2 、智能等待
經過添加 implicitly_wait() 方法就能夠方便的實現智能等待;implicitly_wait(30)
的用法應該比 time.sleep() 更智能,後者只能選擇一個固定的時間的等待,前者能夠
在一個時間範圍內智能的等待。
文檔解釋:
selenium.webdriver.remote.webdriver.implicitly_wait(time_to_wait)
隱式地等待一個無素被發現或一個命令完成;這個方法每次會話只須要調用一次
time_to_wait: 等待時間
用法:
browser.implicitly_wait(30)
# coding = utf-8
fromselenium import webdriver
import time #調入 time 函數
browser =webdriver.Firefox()
browser.get("http://www.baidu.com")
browser.implicitly_wait(30) #智能等待30秒
browser.find_element_by_id("kw").send_keys("selenium")
browser.find_element_by_id("su").click()
browser.quit()
博客園 — 蟲師
http://fnng.cnblogs.com 17
5、打印信息
不少時間咱們不可能盯着腳本執行,咱們須要一些打印信息來證實腳本運行是否正確:
5.1 、打印 tile
把剛纔訪問頁面的 title 打印出來。
coding = utf-8
fromselenium import webdriver
driver = webdriver.Chrome()
driver.get('http://www.baidu.com')
print driver.title # 把頁面 title 打印出來
driver.quit()
雖然我沒看到腳本的執行過程,但我在執行結果裏看到了
>>>
百度一下,你就知道
說明頁面正確被我打開了。
5.2 、打印 URL
能夠將瀏覽器的 title 打印出來,這裏再講個簡單的,把當前 URL 打印出來。其實
也沒啥大用,能夠作個湊數的用例。
#coding=utf-8
fromselenium import webdriver
import time
browser =webdriver.Firefox()
url='http://www.baidu.com'
博客園 — 蟲師
http://fnng.cnblogs.com 18
#經過 get 方法獲取當前 URL 打印
print "now access %s" %(url)
browser.get(url)
time.sleep(2)
browser.find_element_by_id("kw").send_keys("selenium")
browser.find_element_by_id("su").click()
time.sleep(3)
browser.quit()
6、瀏覽器的操做
6.1 、瀏覽器最大化
咱們知道調用啓動的瀏覽器不是全屏的,這樣不會影響腳本的執行,可是有時候會
影響咱們「觀看」腳本的執行。
#coding=utf-8
fromselenium import webdriver
import time
browser =webdriver.Firefox()
browser.get("http://www.baidu.com")
print "瀏覽器最大化"
browser.maximize_window() #將瀏覽器最大化顯示
time.sleep(2)
browser.find_element_by_id("kw").send_keys("selenium")
browser.find_element_by_id("su").click()
time.sleep(3)
browser.quit()
博客園 — 蟲師
http://fnng.cnblogs.com 19
6.2 、設置瀏覽器寬、高
最大化仍是不夠靈活,能不能隨意的設置瀏覽的寬、高顯示?固然是能夠的。
#coding=utf-8
from selenium import webdriver
import time
browser =webdriver.Firefox()
browser.get("http://m.mail.10086.cn")
time.sleep(2)
#參數數字爲像素點
print "設置瀏覽器寬480、高800顯示"
browser.set_window_size(480, 800) time.sleep(3)
browser.quit()
7、操做瀏覽器的前進、後退
瀏覽器上有一個後退、前進按鈕,對於瀏覽網頁的人是比較方便的;對於作 web 自
動化測試的同窗來講應該算是一個比較難模擬的問題;其實很簡單,下面看看 python
的實現方式。
#coding=utf-8
fromselenium import webdriver
import time
browser =webdriver.Firefox()
#訪問百度首頁
first_url= 'http://www.baidu.com'
博客園 — 蟲師
http://fnng.cnblogs.com 20
print "now access %s" %(first_url)
browser.get(first_url)
time.sleep(2)
#訪問新聞頁面
second_url='http://news.baidu.com'
print "now access %s" %(second_url)
browser.get(second_url)
time.sleep(2)
#返回(後退)到百度首頁
print "back to %s "%(first_url)
browser.back()
time.sleep(1)
#前進到新聞頁
print "forwardto %s"%(second_url)
browser.forward()
time.sleep(2)
browser.quit()
爲了使過程讓你看得更清晰,在每一步操做上都加了 print和 sleep 。
說實話,這兩個功能平時不太經常使用,所能想到的場景就是幾個頁面來回跳轉,但又
不想用 get url 的狀況下。
8、操做測試對象
前面講到了很多知識都是定位元素,定位只是第一步,定位以後須要對這個原素進
行操做。鼠標點擊呢仍是鍵盤輸入,這要取決於咱們定位的是按鈕還輸入框。
博客園 — 蟲師
http://fnng.cnblogs.com 21
通常來講,webdriver 中比較經常使用的操做對象的方法有下面幾個
click 點擊對象
send_keys 在對象上模擬按鍵輸入
clear 清除對象的內容,若是能夠的話
submit 清除對象的內容,若是能夠的話
text 用於獲取元素的文本信息
8.1 、鼠標點擊與鍵盤輸入
在咱們本系列開篇的第一個例子裏就用到了到 click 和 send_skys ,別翻回去找
了,我再貼一下代碼:
coding=utf-8
fromselenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(2)
#經過 submit() 來操做
driver.find_element_by_id("su").submit()
time.sleep(3)
driver.quit()
send_keys("xx") 用於在一個輸入框裏輸入 xx 內容。
click() 用於點擊一個按鈕。
clear() 用於清除輸入框的內容,好比百度輸入框裏默認有個「請輸入關鍵
字」的信息,再好比咱們的登錄框通常默認會有「帳號」「密碼」這樣的默認信息。
clear 能夠幫助咱們清除這些信息。
8.2 、submit 提交表單
咱們把「百度一下」的操做從 click 換成 submit 能夠達到相同的效果:
#coding=utf-8
fromselenium import webdriver
import time
博客園 — 蟲師
http://fnng.cnblogs.com 22
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(2)
#經過 submit() 來操做
driver.find_element_by_id("su").submit()
time.sleep(3)
driver.quit()
8.3 、text 獲取元素文本
text 用於獲取元素的文本信息
下面把百度首頁底部的聲明打印輸出
#coding=utf-8
fromselenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
time.sleep(2)
#id = cp 元素的文本信息
data=driver.find_element_by_id("cp").text
print data #打印信息
time.sleep(3)
driver.quit()
輸出:
>>>
©2013 Baidu使用百度前必讀 京 ICP 證030173號
8.4 、get_attribute 得到屬性值
get_attribute
博客園 — 蟲師
http://fnng.cnblogs.com 23
得到屬性值。
這個函數的用法前面已經有出現過,在定位一組元素的時候有使用到它,只是咱們
沒有作過多的解釋。
通常用法:
select = driver.find_element_by_tag_name("select")
allOptions = select.find_elements_by_tag_name("option")
for option in allOptions:
print "Value is: " + option.get_attribute("value")
option.click()
.....
具體應用參考第十一節 層級定位例子。
9、鍵盤事件
本章重點:
鍵盤按鍵用法
鍵盤組合鍵用法
send_keys()輸入中文亂碼問題
9.1 、鍵盤按鍵用法
#coding=utf-8
fromselenium import webdriver
fromselenium.webdriver.common.keys import Keys #須要引入 keys 包
import os,time
driver = webdriver.Firefox()
driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fwebcloud
.kuaibo.com%2F")
博客園 — 蟲師
http://fnng.cnblogs.com 24
time.sleep(3)
driver.maximize_window()# 瀏覽器全屏顯示
driver.find_element_by_id("user_name").clear()
driver.find_element_by_id("user_name").send_keys("fnngj")
#tab 的定位相相於清除了密碼框的默認提示信息,等同上面的 clear()
driver.find_element_by_id("user_name").send_keys(Keys.TAB)
time.sleep(3)
driver.find_element_by_id("user_pwd").send_keys("123456")
#經過定位密碼框,enter(回車)來代替登錄按鈕
driver.find_element_by_id("user_pwd").send_keys(Keys.ENTER)
'''
#也可定位登錄按鈕,經過 enter(回車)代替 click()
driver.find_element_by_id("login").send_keys(Keys.ENTER)
'''
time.sleep(3)
driver.quit()
要想調用鍵盤按鍵操做須要引入keys 包:
fromselenium.webdriver.common.keysimportKeys
經過send_keys()調用按鍵:
send_keys(Keys.TAB) #TAB
send_keys(Keys.ENTER) #回車
注意:這個操做和頁面元素的遍歷順序有關,假如當前定位在帳號輸入框,按鍵
盤的 tab鍵後遍歷的不是密碼框,那就不法輸入密碼。假如輸入密碼後,還有
須要填寫驗證碼,那麼回車也起不到登錄的效果。
9.2 、鍵盤組合鍵用法
#coding=utf-8
fromselenium import webdriver
fromselenium.webdriver.common.keys import Keys
import time
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
博客園 — 蟲師
http://fnng.cnblogs.com 25
#輸入框輸入內容
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(3)
#ctrl+a 全選輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
time.sleep(3)
#ctrl+x 剪切輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')
time.sleep(3)
#輸入框從新輸入內容,搜索
driver.find_element_by_id("kw").send_keys(u"蟲師 cnblogs")
driver.find_element_by_id("su").click()
time.sleep(3)
driver.quit()
上面的操做沒有實際意義,但向咱們演示了鍵盤組合按鍵的用法。
9.3 、中文亂碼問題
selenium2 python 在 send_keys()中輸入中文一直報錯,其實前面加個小 u 就解決了:
coding=utf-8
send_keys(u"輸入中文")
須要注意的是 utf-8並非萬能的,咱們須要保持腳本、瀏覽器、程序三者編碼之
間的轉換;若是 utf-8不能解決,能夠嘗試 GBK或修改瀏覽器的默認編碼。
10、鼠標事件
本 章 重點:
ActionChains類
context_click() 右擊
double_click() 雙擊
drag_and_drop() 拖動
測試的產品中有一個操做是右鍵點擊文件列表會彈出一個快捷菜單,能夠方
便的選擇快捷菜單中的選擇對文件進行操做(刪除、移動、重命名),以前學習
元素的點擊很是簡單:
driver.find_element_by_id(「xxx」).click()
博客園 — 蟲師
http://fnng.cnblogs.com 26
那麼鼠標的雙擊、右擊、拖動等是否也是這樣的寫法呢?例如右擊:
driver.find_element_by_id(「xxx」).context_click()
通過運行腳本獲得了下面的錯誤提示:
AttributeError:'WebElement'objecthasnoattribute'context_click'
提示右點方法不屬於 webelement 對象,經過查找文檔,發現屬於
ActionChains類,但文檔中沒有具體寫法。這裏要感謝 北京-QC-rabbit 的指
點,其實整個python+selenium學習過程都要感謝北京-QC-rabbit的指點。
10.1 、鼠標右鍵
下面介紹鼠標右鍵的用法,以快播私有云爲例:
#coding=utf-8
fromselenium import webdriver
fromselenium.webdriver.common.action_chainsimport ActionChains
import time
driver = webdriver.Firefox()
driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fwebcloud
.kuaibo.com%2F")
#登錄快播私有云
driver.find_element_by_id("user_name").send_keys("username")
driver.find_element_by_id("user_pwd").send_keys("123456")
driver.find_element_by_id("dl_an_submit").click()
time.sleep(3)
#定位到要右擊的元素
qqq
=driver.find_element_by_xpath("/html/body/div/div[2]/div[2]/div/div[3]/table
/tbody/tr/td[2]")
#對定位到的元素執行鼠標右鍵操做
ActionChains(driver).context_click(qqq).perform()
博客園 — 蟲師
http://fnng.cnblogs.com 27
'''
#你也可使用三行的寫法,但我以爲上面兩行寫法更容易理解
chain = ActionChains(driver)
implement=
driver.find_element_by_xpath("/html/body/div/div[2]/div[2]/div/div[3]/table/
tbody/tr/td[2]")
chain.context_click(implement).perform()
'''
time.sleep(3) #休眠3秒
driver.close()
這裏須要注意的是,在使用 ActionChains 類以前,要先將包引入。
右擊的操做會了,下面的其它方法比葫蘆畫瓢也能寫出來。
10.2 、鼠標雙擊
鼠標雙擊的寫法:
#定位到要雙擊的元素
qqq =driver.find_element_by_xpath("xxx")
#對定位到的元素執行鼠標雙擊操做
ActionChains(driver).double_click(qqq).perform()
10.3 、鼠標拖放
鼠標拖放操做的寫法:
#定位元素的原位置
element =driver.find_element_by_name("source")
#定位元素要移動到的目標位置
target = driver.find_element_by_name("target")
博客園 — 蟲師
http://fnng.cnblogs.com 28
#執行元素的移動操做
ActionChains(driver).drag_and_drop(element, target).perform()
11、定位一組元素
webdriver 能夠很方便的使用 findElement 方法來定位某個特定的對象,不過有時
候咱們卻須要定位一組對象,這時候就須要使用 findElements 方法。
定位一組對象通常用於如下場景:
批量操做對象,好比將頁面上全部的 checkbox 都勾上
先獲取一組對象,再在這組對象中過濾出須要具體定位的一些對象。好比定位出頁
面上全部的 checkbox,而後選擇最後一個
checkbox.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Checkbox</title>
<script type="text/javascript" async=""
src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined
.min.css" rel="stylesheet"/>
<script
src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></
script>
</head>
<body>
<h3>checkbox</h3>
<div class="well">
<formclass="form-horizontal">
<divclass="control-group">
<labelclass="control-label" for="c1">checkbox1</label>
<div class="controls">
<input type="checkbox" id="c1" />
</div>
</div>
<divclass="control-group">
博客園 — 蟲師
http://fnng.cnblogs.com 29
<labelclass="control-label" for="c2">checkbox2</label>
<div class="controls">
<input type="checkbox" id="c2" />
</div>
</div>
<divclass="control-group">
<labelclass="control-label" for="c3">checkbox3</label>
<div class="controls">
<input type="checkbox" id="c3" />
</div>
</div>
<divclass="control-group">
<labelclass="control-label" for="r">radio</label>
<div class="controls">
<input type="radio" id="r1" />
</div>
</div>
<divclass="control-group">
<labelclass="control-label" for="r">radio</label>
<div class="controls">
<input type="radio" id="r2" />
</div>
</div>
</form>
</div>
</body>
</html>
將這段代碼保存複製到記事本中,將保存成 checkbox.html文件。(注意,這個頁面須要
和咱們的自動化腳本放在同一個目錄下)
經過瀏覽器打開,獲得下列頁面:
博客園 — 蟲師
http://fnng.cnblogs.com 30
11.1 、第一種定位方法
經過瀏覽器打個這個頁面咱們看到三個複選框和兩個單選框。下面咱們就來定位這
三個複選框。
# -*- coding: utf-8-*-
fromselenium import webdriver
import time
import os
dr =webdriver.Firefox()
file_path= 'file:///' + os.path.abspath('checkbox.html')
dr.get(file_path)
# 選擇頁面上全部的 input,而後從中過濾出全部的 checkbox 並勾選之
inputs = dr.find_elements_by_tag_name('input')
for inputin inputs:
if input.get_attribute('type') == 'checkbox':
input.click()
time.sleep(2)
dr.quit()
import os
博客園 — 蟲師
http://fnng.cnblogs.com 31
注意:由於咱們調用的是本地文件, 因此要導入 os包。
11.2 、第二種定位方法
第二種寫法與第一種寫法差異不大,都是經過一個循環來勾選控件。
# -*- coding: utf-8-*-
fromselenium import webdriver
import time
import os
dr =webdriver.Firefox()
file_path= 'file:///' + os.path.abspath('checkbox.html')
dr.get(file_path)
# 選擇全部的 checkbox 並所有勾上
checkboxes = dr.find_elements_by_css_selector('input[type=checkbox]')
for checkbox in checkboxes:
checkbox.click()
time.sleep(2)
# 打印當前頁面上有多少個 checkbox
print len(dr.find_elements_by_css_selector('input[type=checkbox]'))
time.sleep(2)
dr.quit()
11.3 、去掉最後一個勾選
還有一個問題,有時候咱們並不想勾選頁面的全部的複選框(checkbox),能夠通
過下面辦法把最後一個被勾選的框去掉。以下:
# -*- coding: utf-8-*-
from selenium import webdriver
import time
import os
dr = webdriver.Firefox()
博客園 — 蟲師
http://fnng.cnblogs.com 32
file_path= 'file:///' + os.path.abspath('checkbox.html')
dr.get(file_path)
# 選擇全部的 checkbox 並所有勾上
checkboxes =
dr.find_elements_by_css_selector('input[type=checkbox]')
for checkbox in checkboxes:
checkbox.click()
time.sleep(2)
# 把頁面上最後1個 checkbox的勾給去掉
dr.find_elements_by_css_selector('input[type=checkbox]').pop().cl
ick()
time.sleep(2)
dr.quit()
其實,去掉勾選表也邏輯也很是簡單,就是再次點擊勾選的按鈕。可能咱們比較迷
惑的是如何找到「最後一個」按鈕。pop() 能夠實現這個功能。
12、多層框架/ 窗口定位
本節知識點:
多層框架或窗口的定位:
switch_to_frame()
switch_to_window()
對於一個現代的 web應用,常常會出現框架(frame) 或窗口(window)的應用,
這也就給咱們的定位帶來了一個難題。
有時候咱們定位一個元素,定位器沒有問題,但一直定位不了,這時候就要檢查這
個元素是否在一個 frame 中,seelnium webdriver 提供了一個 switch_to_frame方
法,能夠很輕鬆的來解決這個問題。
12.1 、多層框架定位
frame.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>frame</title>
博客園 — 蟲師
http://fnng.cnblogs.com 33
<script type="text/javascript"
async=""src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
"></script>
<link
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstra
p-combined.min.css" rel="stylesheet" />
<script type="text/javascript">$(document).ready(function(){
});
</script>
</head>
<body>
<div class="row-fluid">
<div class="span10 well">
<h3>frame</h3>
<iframe id="f1" src="inner.html" width="800",
height="600"></iframe>
</div>
</div>
</body>
<script
src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.
min.js"></script>
</html>
inner.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>inner</title>
</head>
<body>
<div class="row-fluid">
<div class="span6 well">
<h3>inner</h3>
<iframe id="f2" src="http://www.baidu.com"
width="700"height="500"></iframe>
<a href="javascript:alert('watir-webdriver betterthan
selenium webdriver;')">click</a>
</div>
</div>
</body>
</html>
frame.html 中嵌套 inner.html ,兩個文件和咱們的腳本文件放同一個目錄下,經過
博客園 — 蟲師
http://fnng.cnblogs.com 34
瀏覽器打開,獲得下列頁面:
下面經過 switch_to_frame() 方法來進行定位:
#coding=utf-8
fromselenium import webdriver
import time
import os
browser =webdriver.Firefox()
file_path= 'file:///' + os.path.abspath('frame.html')
browser.get(file_path)
browser.implicitly_wait(30)
#先找到到 ifrome1(id = f1)
browser.switch_to_frame("f1")
#再找到其下面的 ifrome2(id =f2)
browser.switch_to_frame("f2")
#下面就能夠正常的操做元素了
博客園 — 蟲師
http://fnng.cnblogs.com 35
browser.find_element_by_id("kw").send_keys("selenium")
browser.find_element_by_id("su").click()
time.sleep(3)
browser.quit()
12.2 、多層窗口定位
有可能嵌套的不是框架,而是窗口,還有真對窗口的方法:switch_to_window
用法與 switch_to_frame 相同:
driver.switch_to_window("windowName")
十3、層級定位
假如兩個控件,他們長的一模樣,還都叫「張三」,惟一的不一樣是一個在北京,一
個在上海,那咱們就能夠經過,他們的城市,區,街道,來找到他們。
在實際的測試中也常常會遇到這種問題:頁面上有不少個屬性基本相同的元素,現
在須要具體定位到其中的一個。因爲屬性基本至關,因此在定位的時候會有些麻煩,這
時候就須要用到層級定位。先定位父元素,而後再經過父元素定位子孫元素。
level_locate.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Level Locate</title>
<script type="text/javascript" async=""
src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></scri
pt>
<link
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-c
ombined.min.css" rel="stylesheet" />
</head>
<body>
博客園 — 蟲師
http://fnng.cnblogs.com 36
<h3>Levellocate</h3>
<divclass="span3">
<divclass="well">
<divclass="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown"
href="#">Link1</a>
<ul class="dropdown-menu" role="menu"
aria-labelledby="dLabel"id="dropdown1">
<li><a tabindex="-1" href="#">Action</a></li>
<li><a tabindex="-1" href="#">Another action</a></li>
<li><a tabindex="-1" href="#">Something elsehere</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="#">Separatedlink</a></li>
</ul>
</div>
</div>
</div>
<divclass="span3">
<divclass="well">
<divclass="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown"
href="#">Link2</a>
<ul class="dropdown-menu" role="menu"
aria-labelledby="dLabel">
<li><a tabindex="-1" href="#">Action</a></li>
<li><a tabindex="-1" href="#">Another action</a></li>
<li><a tabindex="-1" href="#">Something elsehere</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="#">Separatedlink</a></li>
</ul>
</div>
</div>
</div>
</body>
<script
src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min
.js"></script>
</html>
上面的 html 代碼比較亂,請複製到編輯器中查看,如 nodepad ++ 編輯器。
(注意,這個頁面須要和咱們的自動化腳本放在同一個目錄下)經過瀏覽器打開:
博客園 — 蟲師
http://fnng.cnblogs.com 37
定位思路:
具體思路是:先點擊顯示出1個下拉菜單,而後再定位到該下拉菜單所在的 ul,再
定位這個 ul 下的某個具體的 link。在這裏,咱們定位第1個下拉菜單中的 Action 這個
選項。
腳本以下:
# -*- coding: utf-8-*-
fromselenium import webdriver
fromselenium.webdriver.support.uiimport WebDriverWait
import time
import os
dr =webdriver.Firefox()
file_path= 'file:///' + os.path.abspath('level_locate.html')
dr.get(file_path)
#點擊 Link1連接(彈出下拉列表)
dr.find_element_by_link_text('Link1').click()
#找到 id 爲 dropdown1的父元素
WebDriverWait(dr, 10).until(lambda the_driver:
the_driver.find_element_by_id('dropdown1').is_displayed())
#在父親元件下找到 link 爲 Action 的子元素
menu = dr.find_element_by_id('dropdown1').find_element_by_link_text('Action')
#鼠標定位到子元素上
webdriver.ActionChains(dr).move_to_element(menu).perform()
time.sleep(2)
博客園 — 蟲師
http://fnng.cnblogs.com 38
dr.quit()
WebDriverWait(dr, 10)
10秒內每隔500毫秒掃描1次頁面變化,當出現指定的元素後結束。dr 就不解釋了,前
面操做 webdriver.firefox()的句柄
is_displayed()
該元素是否用戶能夠見
class ActionChains(driver)
driver: 執行用戶操做實例 webdriver
生成用戶的行爲。全部的行動都存儲在 actionchains 對象。經過 perform()存儲的行爲。
move_to_element(menu)
移動鼠標到一個元素中,menu 上面已經定義了他所指向的哪個元素
to_element:元件移動到
perform()
執行全部存儲的行爲
十4、上傳文件操做
文件上傳操做也比較常見功能之一,上傳功能沒有用到新有方法或函數,關鍵是思
路。
上傳過程通常要打開一個本地窗口,從窗口選擇本地文件添加。因此,通常會卡在
如何操做本地窗口添加上傳文件。
其實,在 selenium webdriver 沒咱們想的那麼複雜;只要定位上傳按鈕,通
send_keys 添加本地文件路徑就能夠了。絕對路徑和相對路徑均可以,關鍵是上傳的文
件存在。下面通地例子演示。
博客園 — 蟲師
http://fnng.cnblogs.com 39
14.1 、操做文件上傳例子
upload_file.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>upload_file</title>
<script type="text/javascript"
async=""src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
"></script>
<link
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstra
p-combined.min.css" rel="stylesheet" />
<script type="text/javascript">
</script>
</head>
<body>
<div class="row-fluid">
<div class="span6 well">
<h3>upload_file</h3>
<input type="file" name="file" />
</div>
</div>
</body>
<script
src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.
min.js"></script>
</html>
經過瀏覽器打開,獲得下列頁面:
操做上傳腳本:
#coding=utf-8
from selenium import webdriver
博客園 — 蟲師
http://fnng.cnblogs.com 40
import os,time
driver = webdriver.Firefox()
#腳本要與 upload_file.html 同一目錄
file_path= 'file:///' + os.path.abspath('upload_file.html')
driver.get(file_path)
#定位上傳按鈕,添加本地文件
driver.find_element_by_name("file").send_keys('D:\\selenium_use_c
ase\upload_file.txt')
time.sleep(2)
driver.quit()
14.2 、139 郵箱上傳
其它有些應用很差找,因此就本身建立頁面,這樣雖然麻煩,但腳本代碼突出重點。
這裏找一139郵箱的實例,有賬號的同窗能夠測試一下~!
(登錄基礎版的139郵箱,網盤模塊上傳文件)
#coding=utf-8
fromselenium import webdriver
import os,time
driver = webdriver.Firefox()
driver.get("http://m.mail.10086.cn")
driver.implicitly_wait(30)
#登錄
driver.find_element_by_id("ur").send_keys("手機號")
driver.find_element_by_id("pw").send_keys("密碼")
driver.find_element_by_class_name("loading_btn").click()
time.sleep(3)
#進入139網盤模塊
driver.find_element_by_xpath("/html/body/div[3]/a[9]/span[2]").click()
博客園 — 蟲師
http://fnng.cnblogs.com 41
time.sleep(3)
#上傳文件
driver.find_element_by_id("id_file").send_keys('D:\\selenium_use_case\upload
_file.txt')
time.sleep(5)
driver.quit()
十5、下拉框處理
本節重點
處理下拉框
switch_to_alert()
accept()
下拉框是咱們最多見的一種頁面元素,對於通常的元素,咱們只須要一次就定位,但下
拉框裏的內容須要進行兩次定位,先定位到下拉框,再定位到下拉框內裏的選項。
15.1 、操做下拉框例子
drop_down.html
<html>
<body>
<select id="ShippingMethod"
onchange="updateShipping(options[selectedIndex]);" name="ShippingMethod">
<option value="12.51">UPS Next Day Air ==> $12.51</option>
<option value="11.61">UPS Next Day Air Saver ==> $11.61</option>
<option value="10.69">UPS 3 Day Select ==> $10.69</option>
<option value="9.03">UPS 2nd Day Air ==> $9.03</option>
<option value="8.34">UPS Ground ==> $8.34</option>
<option value="9.25">USPS Priority Mail Insured ==> $9.25</option>
<option value="7.45">USPS Priority Mail ==> $7.45</option>
<option value="3.20" selected="">USPS First Class ==> $3.20</option>
博客園 — 蟲師
http://fnng.cnblogs.com 42
</select>
</body>
</html>
保存並經過瀏覽器打開,以下:
如今咱們來經過腳本選擇下拉列表裏的 $10.69
#-*-coding=utf-8
fromselenium import webdriver
import os,time
driver= webdriver.Firefox()
file_path= 'file:///' + os.path.abspath('drop_down.html')
driver.get(file_path)
time.sleep(2)
#先定位到下拉框
m=driver.find_element_by_id("ShippingMethod")
#再點擊下拉框下的選項
m.find_element_by_xpath("//option[@value='10.69']").click()
time.sleep(3)
driver.quit()
解析:
這裏可能和以前的操做有所不一樣,首先要定位到下拉框的元素,而後選擇下拉列表
中的選項進行點擊操做。
m=driver.find_element_by_id("ShippingMethod")
m.find_element_by_xpath("//option[@value='10.69']").click()
博客園 — 蟲師
http://fnng.cnblogs.com 43
15.2 、百度搜索設置下拉框操做
#-*-coding=utf-8
fromselenium import webdriver
import os,time
driver= webdriver.Firefox()
driver.get("http://www.baidu.com")
#進入搜索設置頁
driver.find_element_by_link_text("搜索設置").click()
#設置每頁搜索結果爲100條
m=driver.find_element_by_name("NR")
m.find_element_by_xpath("//option[@value='100']").click()
time.sleep(2)
#保存設置的信息
driver.find_element_by_xpath("//input[@value='保存設置']").click()
time.sleep(2)
driver.switch_to_alert().accept()
#跳轉到百度首頁後,進行搜索表(一頁應該顯示100條結果)
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
time.sleep(3)
driver.quit()
解析:
當咱們在保存百度的設置時會會彈出一個肯定按鈕;咱們並沒按照常規的方法去定
位彈窗上的「肯定」按鈕,而是使用:
driver.switch_to_alert().accept()
完成了操做,這是由於彈窗比較是一個具備惟一性的警告信息,因此能夠用這種簡便
的方法處理。
– switch_to_alert()
博客園 — 蟲師
http://fnng.cnblogs.com 44
焦點集中到頁面上的一個警告(提示)
– accept()
接受警告提示
十6、alert 、confirm 、prompt 的處理
本節重點:
text 返回 alert/confirm/prompt 中的文字信息
accept 點擊確認按鈕
dismiss 點擊取消按鈕,若是有的話
send_keys 輸入值,這個 alert\confirm 沒有對話框就不能用了,否則會報錯。
在實際的應用中,咱們會碰到各類交互的彈窗,在上面百度搜索設置的例子中,咱們用
switch_to_alert() 處理警告框很是簡單;其實,對於原生的 js alert 、confirm 以及 prompt
均可以經過 webdriver 的 switch_to_alert()方法進行處理。
比較常見下的就是下面這種類型的確認框:
selenium.webdriver.remote.webdriver.switch_to_alert()
將焦點切換到頁面上的警報
博客園 — 蟲師
http://fnng.cnblogs.com 45
Usage:
driver.switch_to_alert()
因爲用法簡單,這裏就不給具體例子了,在實際應用中:
#接受警告信息
alert = driver.switch_to_alert()
alert.accept()
#獲得文本信息打印
alert = driver.switch_to_alert()
print alert.text()
#取消對話框(若是有的話)
alert = driver.switch_to_alert()
alert.dismiss()
#輸入值
alert = driver.switch_to_alert()
alert.send_keys(「xxx」)
十7、 對話框的處理
本節重點:
打開對話框
關閉對話框
操做對話框中的元素
current_window_handle 得到當前窗口
window_handles 得到全部窗口
更多的時候咱們在實際的應用中碰到的並非簡單警告框,而是提供更多功能的會話
框。
17.1 、div 對話框的處理
modal.html
博客園 — 蟲師
http://fnng.cnblogs.com 46
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>modal</title>
<script type="text/javascript" async=""
src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"
rel="stylesheet" />
<script type="text/javascript">
$(document).ready(function(){
$('#click').click(function(){
$(this).parent().find('p').text('Click on the link to success!');
});
});
</script>
</head>
<body>
<h3>modal</h3>
<div class="row-fluid">
<div class="span6">
<!-- Button to trigger modal -->
<a href="#myModal" role="button" class="btn btn-primary"
data-toggle="modal" id="show_modal">Click</a>
<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1"
role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<p>Congratulations, you open the window!</p>
<a href="#" id="click">click me</a>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal"
aria-hidden="true">Close</button>
<button class="btn btn-primary">Save changes</button>
</div>
</div>
博客園 — 蟲師
http://fnng.cnblogs.com 47
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>modal</title>
<script type="text/javascript" async=""
src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"
rel="stylesheet" />
<script type="text/javascript">
$(document).ready(function(){
$('#click').click(function(){
$(this).parent().find('p').text('Click on the link to success!');
});
});
</script>
</head>
<body>
<h3>modal</h3>
<div class="row-fluid">
<div class="span6">
<!-- Button to trigger modal -->
<a href="#myModal" role="button" class="btn btn-primary"
data-toggle="modal" id="show_modal">Click</a>
<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1"
role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<p>Congratulations, you open the window!</p>
<a href="#" id="click">click me</a>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal"
aria-hidden="true">Close</button>
<button class="btn btn-primary">Save changes</button>
</div>
</div>
博客園 — 蟲師
http://fnng.cnblogs.com 48
</div>
</div>
</body>
<script
src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
</html>
代碼有點長,你能夠直接賦值粘貼到 Notepad++中,保存成 html 經過瀏覽器打開,效
果以下:
操做腳本以下:
# -*- coding: utf-8-*-
fromselenium import webdriver
fromtimeimport sleep
import os
import selenium.webdriver.support.ui asui
if 'HTTP_PROXY'in os.environ:del os.environ['HTTP_PROXY']
dr =webdriver.Firefox()
file_path= 'file:///' +os.path.abspath('modal.html')
dr.get(file_path)
# 打開對話框
dr.find_element_by_id('show_modal').click()
sleep(3)
# 點擊對話框中的連接
博客園 — 蟲師
http://fnng.cnblogs.com 49
# 因爲對話框中的元素被蒙板所遮擋,直接點擊會報 Element is not clickable 的錯誤
# 因此使用 js 來模擬 click
link= dr.find_element_by_id('myModal').find_element_by_id('click')
dr.execute_script('$(arguments[0]).click()',link)
sleep(4)
# 關閉對話框
buttons =
dr.find_element_by_class_name('modal-footer').find_elements_by_tag_name('but
ton')
buttons[0].click()
dr.quit()
17.2 、通常對話框的處理
有些彈出對話框窗,咱們能夠經過判斷是否爲當前窗口的方式進行操做。
#得到當前窗口
nowhandle=driver.current_window_handle
#打開彈窗
driver.find_element_by_name("xxx").click()
#得到全部窗口
allhandles=driver.window_handles
for handle in allhandles:
if handle!=nowhandle: #比較當前窗口是否是原先的窗口
driver.switch_to_window(handle) #得到當前窗口的句柄
dirver.find_element_by_class_name("xxxx").click() #在當前窗口操做
博客園 — 蟲師
http://fnng.cnblogs.com 50
#回到原先的窗口
driver.switch_to_window(nowhandle)
這裏只是操做窗口的代碼片斷,提供一個思路,可否完成咱們想要的結果,還須要咱們
經過實例去驗證。
十8、調用 js
本節重點:
調用 js 方法
execute_script(script, *args)
在當前窗口/框架 同步執行 javaScript
script:JavaScript 的執行。
*args:適用任何 JavaScript 腳本。
使用:
driver.execute_script(‘document.title’)
18.1 、經過 js 隱藏元素
js.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>js</title>
<script type="text/javascript" async=""
src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></s
cript>
<link
博客園 — 蟲師
http://fnng.cnblogs.com 51
href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstra
p-combined.min.css" rel="stylesheet" />
<script type="text/javascript"> $(document).ready(function(){
$('#tooltip').tooltip({"placement": "right"});
});
</script>
</head>
<body>
<h3>js</h3>
<div class="row-fluid">
<div class="span6 well">
<a id="tooltip" href="#" data-toggle="tooltip" title="
selenium-webdriver(python)">hover to see tooltip</a>
<a class="btn">Button</a>
</div>
</div>
</body>
<script
src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.
min.js"></script>
</html>
(保持 html 文件與執行腳本在同一目錄下)
保存並經過瀏覽器打開,以下:
執行 js 通常有兩種場景:
一種是在頁面上直接執行 JS
另外一種是在某個已經定位的元素上執行 JS
#coding=utf-8
fromselenium import webdriver
import time,os
博客園 — 蟲師
http://fnng.cnblogs.com 52
driver = webdriver.Firefox()
file_path= 'file:///' + os.path.abspath('js.html')
driver.get(file_path)
#######經過 JS 隱藏選中的元素##########第一種方法:
driver.execute_script('$("#tooltip").fadeOut();')
time.sleep(5)
#第二種方法:
button = driver.find_element_by_class_name('btn')
driver.execute_script('$(arguments[0]).fadeOut()',button)
time.sleep(5)
driver.quit()
18.2 、經過 js 使輸入框標紅
#coding=utf-8
fromselenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fvod.kuai
bo.com%2F%3Ft%3Dhome")
#給用戶名的輸入框標紅
js="var q=document.getElementById(\"user_name\");q.style.border=\"1px solid
red\";"
#調用 js
driver.execute_script(js)
time.sleep(3)
driver.find_element_by_id("user_name").send_keys("username")
driver.find_element_by_id("user_pwd").send_keys("password")
driver.find_element_by_id("dl_an_submit").click()
博客園 — 蟲師
http://fnng.cnblogs.com 53
time.sleep(3)
driver.quit()
js 解釋:
q=document.getElementById(\"user_name\")
元素 q的 id 爲 user_name
q.style.border=\"1px solid red\
元素 q的樣式,邊框爲1個像素紅色
十9、控制瀏覽器滾動條
有時候咱們須要控制頁面滾動條上的滾動條,但滾動條並不是頁面上的元素,這個時
候就須要藉助 js 是來進行操做。通常用到操做滾動條的會兩個場景:
註冊時的法律條文須要閱讀,判斷用戶是否閱讀的標準是:滾動條是否拉到最
下方。
要操做的頁面元素不在吸視範圍,沒法進行操做,須要拖動滾動條
其實,實現這個功能只要一行代碼,但因爲不懂 js ,因此花了不小力氣找到這種方法。
用於標識滾動條位置的代碼
<body onload= "document.body.scrollTop=0">
<body onload= "document.body.scrollTop=100000">
若是滾動條在最上方的話,scrollTop=0,那麼要想使用滾動條在最可下方,能夠
scrollTop=100000 ,這樣就可使滾動條在最下方。
博客園 — 蟲師
http://fnng.cnblogs.com 54
19.1 、場景一
先來解決場第一個問題,法律條款是一個內嵌窗口,經過 firebug 工具能夠定位到內嵌
入窗口能夠定位到元素的 id ,能夠經過下面的代碼實現。
js="var q=document.getElementById('id').scrollTop=10000"
driver.execute_script(js)
19.2 、場景二
有滾動條的頁面處處可見,這個就比較容易找例子,咱們以操做百度搜索結果頁爲例:
#coding=utf-8
fromselenium import webdriver
import time
#訪問百度
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()
time.sleep(3)
#將頁面滾動條拖到底部
js="var q=document.documentElement.scrollTop=10000"driver.execute_script(js)
time.sleep(3)
#將滾動條移動到頁面的頂部
js="var q=document.documentElement.scrollTop=0"driver.execute_script(js)
time.sleep(3)
driver.quit()
博客園 — 蟲師
http://fnng.cnblogs.com 55
二10、cookie 處理
本節重點:
driver.get_cookies() 得到 cookie 信息
add_cookie(cookie_dict) 向 cookie 添加會話信息
delete_cookie(name) 刪除特定(部分)的 cookie
delete_all_cookies() 刪除全部 cookie
經過 webdriver 操做 cookie是一件很是有意思的事兒,有時候咱們須要瞭解瀏覽器中
是否存在了某個 cookie 信息,webdriver 能夠幫助咱們讀取、添加,刪除 cookie 信息。
20.1 、打印 cookie 信息
#coding=utf-8
fromselenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("http://www.youdao.com")
# 得到 cookie 信息
cookie= driver.get_cookies()
#將得到 cookie 的信息打印
print cookie
driver.quit()
運行打印信息:
[{u'domain': u'.youdao.com', u'secure': False, u'value':
u'aGFzbG9nZ2VkPXRydWU=', u'expiry': 1408430390.991375, u'path': u'/',
u'name': u'_PREF_ANONYUSER__MYTH'}, {u'domain': u'.youdao.com', u'secure':
False, u'value': u'1777851312@218.17.158.115', u'expiry': 2322974390.991376,
u'path': u'/', u'name': u'OUTFOX_SEARCH_USER_ID'}, {u'path': u'/', u'domain':
u'www.youdao.com', u'name': u'JSESSIONID', u'value':
博客園 — 蟲師
http://fnng.cnblogs.com 56
u'abcUX9zdw0minadIhtvcu', u'secure': False}]
20.2 、對 cookie 操做
上面的方式打印了全部 cookie 信息,太多太亂,咱們只想有真對性的打印本身想要
的信息,看下面的例子
#coding=utf-8
fromselenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.youdao.com")
#向 cookie 的 name 和 value 添加會話信息。
driver.add_cookie({'name':'key-aaaaaaa', 'value':'value-bbbb'})
#遍歷 cookies 中的 name 和 value 信息打印,固然還有上面添加的信息
for cookie in driver.get_cookies():
print "%s-> %s" % (cookie['name'], cookie['value'])
# 下面能夠經過兩種方式刪除 cookie# 刪除一個特定的 cookie
driver.delete_cookie("CookieName")
# 刪除全部 cookie
driver.delete_all_cookies()
time.sleep(2)
driver.close()
運行打印信息:
YOUDAO_MOBILE_ACCESS_TYPE -> 1
_PREF_ANONYUSER__MYTH ->aGFzbG9nZ2VkPXRydWU=
OUTFOX_SEARCH_USER_ID ->-1046383847@218.17.158.115
JSESSIONID -> abc7qSE_SBGsVgnVLBvcu
key-aaaaaaa ->value-bbbb # 這一條是咱們本身添加的
博客園 — 蟲師
http://fnng.cnblogs.com 57
20.3 、博客園登錄分析cookie
經過博客園登錄來分析 cookie
#coding=utf-8
fromselenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://passport.cnblogs.com/login.aspx?ReturnUrl=http://www.cnbl
ogs.com/fnng/admin/EditPosts.aspx")
time.sleep(3)
driver.maximize_window()# 瀏覽器全屏顯示
#經過用戶名密碼登錄
driver.find_element_by_id("tbUserName").send_keys("fnngj")
driver.find_element_by_id("tbPassword").send_keys("123456")
#勾選保存密碼
driver.find_element_by_id("chkRemember").click()
time.sleep(3)
#點擊登錄按鈕
driver.find_element_by_id("btnLogin").click()
#獲取 cookie 信息並打印
cookie= driver.get_cookies()
print cookie
time.sleep(2)
driver.close()
運行打印信息:
#第一次執行信息
>>>
[{u'domain': u'.cnblogs.com', u'name': u'.DottextCookie', u'value':
u'C709F15A8BC0B3E8D9AD1F68B371053849F7FEE31F73F1292A150932FF09A7B0D4A1B449A3
2A6B24AD986CDB05B9998471A37F39C3B637E85E481AA986D3F8C187D7708028F9D4ED3B326B
46DC43B416C47B84D706099ED1D78B6A0FC72DCF948DB9D5CBF99D7848FDB78324',
博客園 — 蟲師
http://fnng.cnblogs.com 58
u'expiry': None, u'path': u'/', u'secure': False}]
>>> =========================RESTART ================================
#第二次執行信息
>>>
[{u'domain': u'.cnblogs.com', u'name': u'.DottextCookie', u'value':
u'5BB735CAD62E99F8CCB9331C32724E2975A0150D199F4243AD19357B3F99A416A93B2E803F
4D5C9D065429713BE8B5DB4ED760EDCBAF492EABE2158B3A6FBBEA2B95C4DA3D2EFEADACC324
7040906F1462731F652199E2A8BEFD8A9B6AAE87CF3059A3CAEB9AB0D8B1B7AD2A',
u'expiry': 1379502502, u'path': u'/', u'secure': False}]
>>>
第一次註釋掉勾選保存密碼的操做,第二次經過勾選保存密碼得到 cookie 信息 ;
來看兩次運行結果的 cookie 的何不一樣:
u'expiry': None
u'expiry': 1379502502
經過對比發現,不勾選保存密碼時 expiry 的值爲 none ; 那麼就能夠初步判斷勾選
保存密碼的操做在 cookie 中起到了做用。至因而否準確能夠再作進一步的分析。
二11、webdriver 原理解析
以前看乙醇視頻中提到,selenium 的 ruby 實現有一個小後門,在代碼前加上
$DEBUG=1 ,再運行腳本的過程當中,就能夠看到客戶端請求的信息與服務器端返回的數據;
以爲這個功能很強大,能夠幫助理解 webdriver 的運行原理。
後來查了半天,python 並無提供這樣一個方便的後門,不過咱們能夠經過代理的方式
得到這些交互信息;
1、須要安裝 java 虛擬機與 selenium-server-standalone ,參考本文檔第一章環境搭
建第七、8步操做。
2、經過下面命令啓動服務:
C:\selenium>java -jar selenium-server-standalone-2.33.0.jar
在命令結尾加 >d:\log.txt 能夠將命令信息存入文件,但信息不多。
運行下面的自動化腳本:
博客園 — 蟲師
http://fnng.cnblogs.com 59
#coding =utf-8
import time
fromselenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = webdriver.Remote(desired_capabilities=DesiredCapabilities.CHROME)
driver.get("http://www.youdao.com")
driver.find_element_by_name("q").send_keys("hello")
driver.find_element_by_name("q").send_keys("key.ENTER")
driver.close()
webdriver 原理:
1. WebDriver 啓動目標瀏覽器,並綁定到指定端口。該啓動的瀏覽器實例,作爲 web driver
的 remote server。
2. Client 端經過 CommandExcuter 發送 HTTPRequest 給 remote server 的偵聽端口(通訊
協議: the webriver wire protocol)
3. Remote server 須要依賴原生的瀏覽器組件(如:IEDriver.dll,chromedriver.exe),來轉
化轉化瀏覽器的 native 調用。
查看命令提示符下的運行日誌:
咋一看很亂,慢慢分析一下就發現頗有意思!結合上面的腳本分析
------------------------------------------------------------------------啓動代理進入監聽狀態
C:\selenium>java -jarselenium-server-standalone-2.33.0.jar
八月 22, 201310:19:48 上午org.openqa.grid.selenium.GridLaunchermain
INFO:Launchingastandalone server
10:19:48.734 INFO-Java:Oracle Corporation 23.21-b01
10:19:48.734 INFO-OS:WindowsXP 5.1 x86
10:19:48.734 INFO-v2.33.0, withCore v2.33.0.Builtfrom revision4e90c97
10:19:48.843INFO - RemoteWebDriver instances shouldconnectto:http://127.0.0.
1:4444/wd/hub
10:19:48.843 INFO-VersionJetty/5.1.x
10:19:48.843 INFO-StartedHttpContext[/selenium-server/driver,/selenium-server
/driver]
博客園 — 蟲師
http://fnng.cnblogs.com 60
10:19:48.843 INFO-StartedHttpContext[/selenium-server,/selenium-server]
10:19:48.843 INFO-StartedHttpContext[/,/]
10:19:48.890 INFO-Startedorg.openqa.jetty.jetty.servlet.ServletHandler@176343e
10:19:48.890 INFO-StartedHttpContext[/wd,/wd]
10:19:48.906INFO - Started SocketListeneron 0.0.0.0:4444
10:19:48.906 INFO-Startedorg.openqa.jetty.jetty.Server@388c74
--------------------------------------------------------------------------------------
建立新 session
10:20:38.593 INFO-Executing: [newsession: {platform=ANY,javascriptEnabled=tr
ue,browserName=chrome,version=}] atURL: /session)
10:20:38.593 INFO-Creating a new session for Capabilities[{platform=ANY,java
scriptEnabled=true,browserName=chrome,version=}]
webdrivr 經過 GET 方式發送請求
[0.921][INFO]: receivedWebriver request:GET/status
向 webdrver 返回響應,返回碼200表示成功
[0.921][INFO]: sending Webriverresponse:200{
"sessionId":"",
"status": 0,
"value":{
"build": {
"version":"alpha" },
"os":{
"arch": "x86",
"name": "WindowsNT",
"version":"5.1 SP3" }
}
}
webdriver再次以 POST 方式發送請求,並啓動瀏覽器相關信息
[0.984][INFO]: receivedWebriver request:POST /session{
"desiredCapabilities":{
"browserName": "chrome",
"javascriptEnabled": true,
"platform":"ANY",
"version": "" }
博客園 — 蟲師
http://fnng.cnblogs.com 61
}
[0.984][INFO]:Launchingchrome:"C:\ocuments and Settings\Administrator\LocalS
ettings\Application ata\Google\Chrome\Application\chrome.exe" --remote-debugging
-port=4223--no-first-run --enable-logging--logging-level=1--user-data-dir="C:
\OCUME~1\AMINI~1\LOCALS~1\Temp\scoped_dir1808_7550"
--load-extension="C:\OCUME~1\AMINI~1\LOCALS~1\Temp\scoped_dir1808_26821\internal"
--ignore-certificate-error
sdata:text/html;charset=utf-8,
[1.773][INFO]: sending Webriverresponse:303
webdriver 再次以GET 方法請求,這附加上了session 的信息
[1.778][INFO]: receivedWebriver request:GET/session/32b33aa585ccbbf7ba7853588
2852af3
服務器先對 sesssionID 進行解析,確認是 selenium調用的以及要訪問的網址,
[1.779][INFO]: sending Webriverresponse:200{
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
"status": 0,
"value":{
"acceptSslCerts":true,
"applicationCacheEnabled": false,
"browserConnectionEnabled":false,
"browserName": "chrome",
"chrome":{
"chromedriverVersion":"2.0" },
"cssSelectorsEnabled": true,
"databaseEnabled": true,
"handlesAlerts": true,
"javascriptEnabled": true,
"locationContextEnabled":true,
"nativeEvents":true,
"platform":"Windows NT",
"rotatable": false,
"takesScreenshot": true,
"version": "27.0.1453.116",
"webStorageEnabled": true }
}
10:20:40.640 INFO-Done:/session
博客園 — 蟲師
http://fnng.cnblogs.com 62
10:20:40.640 INFO-Executing: org.openqa.selenium.remote.server.handler.GetSess
ionCapabilities@14cf7a1at URL:/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc)
10:20:40.640 INFO-Done:/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc
10:20:40.656INFO - Executing:[get:http://www.youdao.com] atURL: /session/ac5
b2c71-5b1a-469e-814c-fdd09a2061fc/url)
webdriver 正試向服務器請求youdao 網站
[1.820][INFO]: receivedWebriver request:POST /session/32b33aa585ccbbf7ba785358
82852af3/url {
"url":"http://www.youdao.com"}
[1.822][INFO]: waiting for pending navigations...
[1.829][INFO]: donewaitingforpendingnavigations
[2.073][INFO]: waiting for pending navigations...
[2.900][INFO]: donewaitingforpendingnavigations
得到服務器數據的應答
[2.900][INFO]: sending Webriverresponse:200{
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
"status": 0,
"value":null}
10:20:41.734 INFO-Done:/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/url
--------------------------------------------------------------下面接着發送定位輸入框的信息
10:20:41.734 INFO-Executing: [find element:By.name: q]at URL:/session/ac5b2
c71-5b1a-469e-814c-fdd09a2061fc/element)
[2.905][INFO]: receivedWebriver request:POST /session/32b33aa585ccbbf7ba785358
82852af3/element {
"using":"name",
"value":"q"}
[2.905][INFO]: waiting for pending navigations...
[2.905][INFO]: donewaitingforpendingnavigations
[2.922][INFO]: waiting for pending navigations...
[2.922][INFO]: donewaitingforpendingnavigations
獲得服務器應答
[2.922][INFO]: sending Webriverresponse:200{
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
博客園 — 蟲師
http://fnng.cnblogs.com 63
"status": 0,
"value":{
"ELEMENT": "0.19427558477036655:1" }
}
10:20:41.765 INFO-Done:/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element
10:20:41.765 INFO-Executing: [send keys: 0 org.openqa.selenium.support.events.
EventFiringWebDriver$EventFiringWebElement@a8215ba9, [h, e,l, l,o]]at URL:/s
ession/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/0/value)
向定位到的輸入框寫入 hello
[2.936][INFO]: receivedWebriver request:POST /session/32b33aa585ccbbf7ba785358
82852af3/element/0.19427558477036655:1/value {
"id": "0.19427558477036655:1",
"value":["h", "e","l", "l","o"]
}
[2.936][INFO]: waiting for pending navigations...
[2.936][INFO]: donewaitingforpendingnavigations
[3.002][INFO]: waiting for pending navigations...
[3.002][INFO]: donewaitingforpendingnavigations
[3.002][INFO]: sending Webriverresponse:200{
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
"status": 0,
"value":null}
10:20:41.843INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/
0/value
再次發送定位輸入框的請求
10:20:41.843 INFO-Executing: [find element:By.name: q]at URL:/session/ac5b2
c71-5b1a-469e-814c-fdd09a2061fc/element)
[3.006][INFO]: receivedWebriver request:POST /session/32b33aa585ccbbf7ba785358
82852af3/element {
"using":"name",
"value":"q"}
[3.006][INFO]: waiting for pending navigations...
[3.006][INFO]: donewaitingforpendingnavigations
[3.016][INFO]: waiting for pending navigations...
博客園 — 蟲師
http://fnng.cnblogs.com 64
[3.016][INFO]: donewaitingforpendingnavigations
[3.016][INFO]: sending Webriverresponse:200{
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
"status": 0,
"value":{
"ELEMENT": "0.19427558477036655:1" }
}
10:20:41.859 INFO-Done:/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element
10:20:41.859 INFO-Executing: [send keys: 0 org.openqa.selenium.support.events.
EventFiringWebDriver$EventFiringWebElement@a8215ba9, [k, e,y, .,E, N,T, E,R]
]at URL:/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/0/value)
對定位的到的輸入框發送回車(ENTER)事件請求
[3.021][INFO]: receivedWebriver request:POST /session/32b33aa585ccbbf7ba785358
82852af3/element/0.19427558477036655:1/value {
"id": "0.19427558477036655:1",
"value":["k", "e","y", ".","E", "N","T", "E","R"]
}
[3.021][INFO]: waiting for pending navigations...
[3.021][INFO]: donewaitingforpendingnavigations
[3.064][INFO]: waiting for pending navigations...
[3.064][INFO]: donewaitingforpendingnavigations
[3.064][INFO]: sending Webriverresponse:200{
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
"status": 0,
"value":null}
10:20:41.906INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/
0/value
10:20:41.906 INFO - Executing: [close window] at URL:
/session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/window)
[3.068][INFO]: receivedWebriver request:ELETE/session/32b33aa585ccbbf7ba78535
882852af3/window
[WARNING:chrome_desktop_impl.cc(88)] chromedetaches,user shouldtake careof d
irectory:C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\scoped_dir1808_7550andC:\DOCUME~1\
ADMINI~1\LOCALS~1\Temp\scoped_dir1808_26821
[5.318][INFO]: sending Webriverresponse:200{
博客園 — 蟲師
http://fnng.cnblogs.com 65
"sessionId":"32b33aa585ccbbf7ba78535882852af3",
"status": 0,
"value":null}
10:20:44.156INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/window
第二部分:框架的力量
博客園 — 蟲師
http://fnng.cnblogs.com 66
二12、引入 unittest 框架
unittest 框架學習
藉助 IED 錄製腳本,
博客園 — 蟲師
http://fnng.cnblogs.com 67
將腳本導出,保存爲 baidu.py ,經過 python IDLE 編輯器打開。以下:
fromselenium import webdriver
fromselenium.webdriver.common.by import By
fromselenium.webdriver.common.keys import Keys
fromselenium.webdriver.support.uiimport Select
fromselenium.common.exceptions import NoSuchElementException
import unittest, time, re
class Baidu(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com/" self.verificationErrors =
[]
self.accept_next_alert =True
def test_baidu(self):
driver = self.driver
driver.get(self.base_url+ "/")
driver.find_element_by_id("kw").send_keys("selenium webdriver")
driver.find_element_by_id("su").click()
driver.close()
def is_element_present(self, how, what):
博客園 — 蟲師
http://fnng.cnblogs.com 68
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()
加入 unittest 框架後,看上去比咱們以前見的腳本複雜了不少,除了中間操做瀏覽器的幾行,
其它都看不懂,不要急,咱們來分析一下~!
import unittest
相想使用 unittest 框架,首先要引入 unittest 包,這個很少解釋。
class Baidu(unittest.TestCase):
Baidu 類繼承 unittest.TestCase 類,從 TestCase 類繼承是告訴 unittest 模塊的方式,
這是一個測試案例。
def setUp(self):
self.driver = webdriver.Firefox()
博客園 — 蟲師
http://fnng.cnblogs.com 69
self.base_url = "http://www.baidu.com/"
setUp 用於設置初始化的部分,在測試用例執行前,這個方法中的函數將先被調用。
這裏將瀏覽器的調用和 URL 的訪問放到初始化部分。
self. verificationErrors =[]
腳本運行時,錯誤的信息將被打印到這個列表中。
self.accept_next_alert =True
是否繼續接受下一下警告(字面意思,沒找到解釋!)
def test_baidu(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("kw" ).send_keys( "selenium webdriver")
driver.find_element_by_id("su" ).click()
test_baidu 中放置的就是咱們的測試腳本了,這部分咱們並不陌生;由於咱們執行的
腳本就在這裏。
def is_element_present(self, how, what):
try : self.driver.find_element(by=how, value= what)
except NoSuchElementException, e: return False
return True
is_element_present 函數用來查找頁面元素是否存在,在這裏用處不大,一般刪除。
由於判斷頁面元素是否存在通常都加在 testcase 中。
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:
博客園 — 蟲師
http://fnng.cnblogs.com 70
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
returnalert_text
finally :self.accept_next_alert =True
關閉警告和對獲得文本框的處理,若是不熟悉 python 的異常處理和 if 語句的話,
請去補基礎知識,這裏很少解釋。
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
tearDown 方法在每一個測試方法執行後調用,這個地方作全部清理工做,如退出
瀏覽器等。
self.assertEqual([], self.verificationErrors)
這個是難點,對前面 verificationErrors 方法得到的列表進行比較;如查
verificationErrors 的列表不爲空,輸出列表中的報錯信息。
並且,這個東西,也能夠未來被你本身更好的調用和使用,根據本身的須要寫入你
但願的信息。(rabbit 告訴個人)
if __name__ == "__main__":
unittest.main()
unitest.main()函數用來測試 類中以 test 開頭的測試用例
這樣一一分析下來,咱們對 unittest框架有了初步的瞭解。運行腳本,由於引入了unittest 框
架,因此控制檯輸出了腳本執行狀況的信息。
>>> =========================RESTART ================================
>>>
.
----------------------------------------------------------------------
Ran 1 test in 10.656s
OK
>>>
博客園 — 蟲師
http://fnng.cnblogs.com 71
很帥吧!? 後面將以 unittest 爲基礎,向新的征程進發~!
二十3、unittest 單元測試框架解析
上一節只是從自動化測試的角度簡單分析了一下 unittest ,這一節從 python 的單元測
試框架的角度再學習一下 unittest 框架(又名 PyUnit 框架)
(好好學,這一章整不明白,後面的技術就別玩了!)
widget.py---被測試類
#coding= utf-8
# 將要被測試的類
class Widget:
def __init__(self, size = (40, 40)):
self._size= size
def getSize(self):
return self._size
def resize(self, width, height):
ifwidth < 0 or height < 0:
raise ValueError, "illegal size"
self._size= (width, height)
def dispose(self):
pass
auto.py---測試類
#coding= utf-8
from widget import Widget
import unittest
# 執行測試的類
class WidgetTestCase(unittest.TestCase):
博客園 — 蟲師
http://fnng.cnblogs.com 72
def setUp(self):
self.widget = Widget()
def testSize(self):
self.assertEqual(self.widget.getSize(), (40, 40))
def tearDown(self):
self.widget = None
# 構造測試集
def suite():
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase("testSize"))
return suite
# 測試
if__name__ == "__main__":
unittest.main(defaultTest = 'suite')
用 import 語句引入 unittest 模塊
讓全部執行測試的類都繼承於 TestCase 類,能夠將 TestCase 當作是對特定類進行
測試的方法的集合
setUp()方法中進行測試前的初始化工做,tearDown()方法中執行測試後的清除工
做。setUp()和 tearDown()都是 TestCase 類中定義的方法
在 testSize()中調用 assertEqual()方法,對 Widget 類中 getSize()方法的返
回值和預期值進行比較,確保二者是相等的,assertEqual()也是 TestCase 類中
定義的方法。
提供名爲 suite()的全局方法,PyUnit 在執行測試的過程調用 suit()方法來肯定
有多少個測試用例須要被執行,能夠將 TestSuite 當作是包含全部測試用例的一個容
器。
框架分析
軟件測試中最基本的組成是單元測試用例(testcase),咱們在實際測試過程當中,不
可能真對一個功能(類)只寫一個用例。TestCase 在 PyUnit 測試框架中被視爲測試單
元的運行實體,Python 程序員能夠經過它派生自定義的測試過程與方法(測試單元),利
博客園 — 蟲師
http://fnng.cnblogs.com 73
用 Command 和 Composite 設計模式,多個 TestCase 還能夠組合成測試用例集合。
編寫測試用例
採用 PyUnit 提供的動態方法,只編寫一個測試類來完成對整個軟件模塊的測試,這樣
對象的初始化工做能夠在 setUp()方法中完成,而資源的釋放則能夠在 tearDown()方法中完
成。
對的 widget.py 被測試類的多方法進行測試
# 執行測試的類
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget()
# 測試 getSize()方法的測試用例
def testSize(self):
self.assertEqual(self.widget.getSize(), (40, 40))
# 測試 resize()方法的測試用例
def testResize(self):
self.widget.resize(100, 100)
self.assertEqual(self.widget.getSize(), (100, 100))
def tearDown(self):
self.widget.dispose()
self.widget = None
咱們能夠在一個測試類中,寫多個測試用例對被測試類的方法進行測試。
組織用例集
完整的單元測試不多隻執行一個測試用例,開發人員一般都須要編寫多個測試用例才能
對某一軟件功能進行比較完整的測試,這些相關的測試用例稱爲一個測試用例集,在
PyUnit 中是用 TestSuite 類來表示的。
能夠在單元測試代碼中定義一個名爲 suite()的全局函數,並將其做爲整個單元測試
博客園 — 蟲師
http://fnng.cnblogs.com 74
的入口,PyUnit 經過調用它來完成整個測試過程。
def suite():
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase("testSize"))
suite.addTest(WidgetTestCase("testResize"))
return suite
若是用於測試的類中全部的測試方法都以 test 開頭,Python程序員甚至能夠用
PyUnit 模塊提供的 makeSuite()方法來構造一個。
def suite():
return unittest.makeSuite(WidgetTestCase, "test")
TestSuite 類能夠當作是 TestCase 類的一個容器,用來對多個測試用例進行組織,這樣多
個測試用例能夠自動在一次測試中所有完成。
運行測試集
PyUnit 使用 TestRunner 類做爲測試用例的基本執行環境,來驅動整個單元測試過程。
Python 開發人員在進行單元測試時通常不直接使用 TestRunner 類,而是使用其子類
TextTestRunner 來完成測試,並將測試結果以文本方式顯示出來:
runner= unittest.TextTestRunner()
runner.run(suite)
對 widget.py 被測試類,下面經過 PyUnit 編寫完整的單元測試用例:
text_runner.py
#coding=utf-8
from widget import Widget
import unittest
# 執行測試的類
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget()
def tearDown(self):
self.widget.dispose()
self.widget = None
博客園 — 蟲師
http://fnng.cnblogs.com 75
def testSize(self):
self.assertEqual(self.widget.getSize(), (40, 40))
def testResize(self):
self.widget.resize(100, 100)
self.assertEqual(self.widget.getSize(), (100, 100))
# 測試
if__name__ == "__main__":
# 構造測試集
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase("testSize"))
suite.addTest(WidgetTestCase("testResize"))
# 執行測試
runner= unittest.TextTestRunner()
runner.run(suite)
PyUnit 模塊中定義了一個名爲 main 的全局方法,使用它能夠很方便地將一個單元測
試模塊變成能夠直接運行的測試腳本,main()方法使用 TestLoader 類來搜索全部包含
在該模塊中的測試方法,並自動執行它們。若是 Python 程序員可以按照約定(以 test
開頭)來命名全部的測試方法,那就只須要在測試模塊的最後加入以下幾行代碼便可:
#coding=utf-8
from widget import Widget
import unittest
# 執行測試的類
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget()
def tearDown(self):
self.widget.dispose()
self.widget = None
def testSize(self):
self.assertEqual(self.widget.getSize(), (40, 40))
def testResize(self):
self.widget.resize(100, 100)
self.assertEqual(self.widget.getSize(), (100, 100))
# 測試
博客園 — 蟲師
http://fnng.cnblogs.com 76
if__name__ == "__main__":
unittest.main()
二十4、批量執行測試集
有了上面對 unittest 框架的學習做鋪墊,下面咱們就能夠將多個自動化用例用到一塊兒執
行。
#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.uiimport Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
class Baidu(unittest.TestCase):
def setUp(self):
self.driver =webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com/"
self.verificationErrors = []
self.accept_next_alert = True
#百度搜索用例
def test_baidu_search(self):
driver = self.driver
driver.get(self.base_url +"/")
driver.find_element_by_id("kw").send_keys("selenium webdriver")
driver.find_element_by_id("su").click()
time.sleep(2)
driver.close()
#百度設置用例
def test_baidu_set(self):
driver = self.driver
博客園 — 蟲師
http://fnng.cnblogs.com 77
#進入搜索設置頁
driver.get(self.base_url +"/gaoji/preferences.html")
#設置每頁搜索結果爲 100 條
m=driver.find_element_by_name("NR")
m.find_element_by_xpath("//option[@value='100']").click()
time.sleep(2)
#保存設置的信息
driver.find_element_by_xpath("//input[@value='保存設置']").click()
time.sleep(2)
driver.switch_to_alert().accept()
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if__name__ == "__main__":
unittest.main()
雖然已經實例了多個用例一塊兒跑,但這樣仍然不合理,幾個用例一塊兒執行還好,若是幾
十個、幾百個的用例的話,這個文件將變得無比龐大,不利於維護。
因此,作合理的作法是一個例一個文件,把所文件放一個文件夾下,經過單獨的腳本控
制全部用例的執行,將腳本的執行結果輸出到一個 log 文件中。
初步把框架走通了。
單個用例相信你早就會寫了,把他們整理一下放到一個文件夾下,而後編寫執行用例集
的腳本:
博客園 — 蟲師
http://fnng.cnblogs.com 78
test_case_.py
#-*-coding=utf-8-*-
import os
#列出某個文件夾下的全部 case,這裏用的是 python,所在 py 文件運行一次後會生成一個 pyc
的副本
caselist=os.listdir('D:\\selenium_use_case\\test_case')
for a in caselist:
s=a.split('.')[1:][0] #選取所要執行的用例
ifs=='py':
#此處執行 dos 命令並將結果保存到log.txt
os.system('D:\\selenium_use_case\\test_case\\%s 1>>log.txt 2>&1'%a)
查看 log.txt 文件:
..
----------------------------------------------------------------------
Ran 2 tests in 32.469s
OK
..
----------------------------------------------------------------------
Ran 2 tests in 27.016s
OK
二十5、異常捕捉與錯誤截圖
建立錯誤截圖文件夾,目錄結果以下:
用例不可能每一次運行都成功,確定運行時候有不成功的時候,換句話說,咱們不須要
永遠都運行成功的用例,他自己是沒有什麼意義的。關鍵是咱們捕捉到錯誤,並以把並錯誤
博客園 — 蟲師
http://fnng.cnblogs.com 79
截圖保存,這將是一個很是棒的功能,也會給咱們錯誤定位帶來方便。
baidu.py
#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.uiimport Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
class Baidu(unittest.TestCase):
def setUp(self):
self.driver =webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com/"
self.verificationErrors = []
self.accept_next_alert = True
#百度搜索用例
def test_baidu_search(self):
driver = self.driver
driver.get(self.base_url +"/")
try:
#kwddd 是一個沒法找到的元素id
driver.find_element_by_id("kwdddd").send_keys("selenium webdriver")
except:
driver.get_screenshot_as_file("D:\\selenium_use_case\\error_png\\kw.png")
#若是沒有找到上面的元素就截取當前頁面。
driver.find_element_by_id("su").click()
time.sleep(2)
driver.close()
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if__name__ == "__main__":
unittest.main()
這裏特地把腳本寫錯誤的,使腳本找不到 id 爲 kwddd 的元素,經過 try....except...對
博客園 — 蟲師
http://fnng.cnblogs.com 80
異常進行捕捉;並把結果保存下來。再次執行你的腳本會發現 error_png 目錄下面產生了
錯誤時候的截圖。
截圖函數 get_screenshot_as_file
selenium.webdriver.remote.webdriver.get_screenshot_as_file(filename)
截圖當前窗口圖片。若是有任何 IOError 將返回 false ,不然將返回 Ture .
filename: 指定錯誤截圖的存放路徑及圖片名。
用法:
driver.get_screenshot_as_file(’/Screenshots/foo.png’)
咱們須要用 python這門語言去調用 selenium 的一些工具來操做瀏覽器,幫助咱們實現
「web UI 」自動化。
===================華麗分割線======================
下面的內容爲本文檔第三版的內容,後面的學習重點就不是經過 webdriver如何操做頁
面元素了,咱們的關注點將轉移到框架上,如何 python 語言使咱們的框架實現更強大的功
能,我在後面的章節學習與整理的過程當中,也補充了很多 python 知識,建議讀者最好掌握
一些 python 編程基礎。
博客園 — 蟲師
http://fnng.cnblogs.com 81
二十6、生成測試報告(HTMLTestRunner)
在腳本雲行完成以後,除了在 log.txt 文件看到運行日誌外,咱們更但願能生一張漂亮
的測試報告來展現用例執行的結果。
下面咱們就經過 HTMLTestRunner.py 來生成測試報告。
首先要下 HTMLTestRunner.py 文件,下載 地址:
http://tungwaiyip.info/software/HTMLTestRunner.html
將下載的文件放入...\Python27\Lib 目錄下(windows),打開交互模式引入包,若是沒有
報錯,說明添加成功,固然也能夠經過 dir() 看看'HTMLTestRunner 包含發哪些方法。
>>> importHTMLTestRunner
>>> dir(HTMLTestRunner)
['HTMLTestRunner', 'OutputRedirector', 'StringIO', 'Template_mixin', 'TestProgram', 'TestResult',
'_TestResult', '__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__',
'__version__', 'datetime', 'main', 'saxutils', 'stderr_redirector', 'stdout_redirector', 'sys', 'time',
'unittest']
>>>
ok ! 下面在咱們用例中添加能夠生成報告的代碼:
#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.uiimport Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
import HTMLTestRunner
class Baidu(unittest.TestCase):
博客園 — 蟲師
http://fnng.cnblogs.com 82
def setUp(self):
self.driver =webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com"
self.verificationErrors = []
self.accept_next_alert = True
#測試用例一
def test_baidu_search(self):
#測試用例二
def test_baidu_set(self):
#測試用例三
def test_baidu_xxx(self):
....
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)if __name__ == "__main__":
if__name__ == "__main__":
testunit=unittest.TestSuite() #定義一個單元測試容器
testunit.addTest(Baidu("test_baidu_search")) #將測試用例加入到測試容器中
testunit.addTest(Baidu("test_baidu_set"))
testunit.addTest(Baidu("test_baidu_xxx"))
filename = 'D:\\result.html' #定義個報告存放路徑,支持相對路徑。
博客園 — 蟲師
http://fnng.cnblogs.com 83
fp = file(filename, 'wb')
runner =HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='Report_title',
description='Report_description')
runner.run(testunit) #自動進行測試
代碼分析:
用例的部分經過以前的學習已經很是瞭解了,下面重點分析底部這段代碼:
testunit=unittest.TestSuite() #定義一個單元測試容器
testunit.addTest(Baidu("test_baidu_search")) #將測試用例加入到測試容器中
testunit.addTest(Baidu("test_baidu_set"))
testunit.addTest(Baidu("test_baidu_xxx"))
filename = 'D:\\result.html' #定義個報告存放路徑,支持相對路徑。
fp = file(filename, 'wb')
runner =HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='Report_title',
description='Report_description')
runner.run(testunit) #自動進行測試
TestSuite 其實並不陌生,在 23 章 章 unittest 單元測試框架分析的部分已經介紹,只是爲
了方便咱們使用了 unittest.main() 方法,默認會將全部用例執行。由於這裏要生成報告,所
以要將全部用例列出;
博客園 — 蟲師
http://fnng.cnblogs.com 84
下面的也很容易理解,建立 result.html 文件,給以讀寫權限(wb),調用HTMLTestRunner
文件,並將測試結果以HTMLTestRunner 規定的格式經過fp 傳遞寫入到result.html 文件中。
最後是運行的 testunit ,也就是 TestSuite 中的全部用例。
腳本運行結束,生成以下報告:
問題:
這個報告是根據一個.py 文件生成的,這樣就迫使咱們把全部用例都寫在一個.py 文件
裏,若是咱們每個用例都寫在不一樣的.py 文件裏將生成不少個報告,不便於閱讀;但寫在
一個.py 文件裏,若是用例很是多的話,一樣不便於維護。
後面,咱們將一塊兒尋求解決辦法。
二十7、數據驅動測試
先來理解一下自動化領域的兩種驅動,對象驅動與數據驅動。
數據驅動:測試數據的改變引發執行結果的改變 叫 數據驅動;
關鍵字驅動:測試對象名字的改變起引發測試結果的改變 叫 關鍵字驅動。
27.1 、讀取文件參數化
博客園 — 蟲師
http://fnng.cnblogs.com 85
以百度表搜索爲例,咱們能夠經過腳本循環執行,讀取一文件中不一樣的內容來完成自動
化工做,也就是說咱們每次取的文件裏的搜索關鍵字不一樣,而每次百度搜索的的結果不一樣,
這也是數據驅動的本質。
代碼以下:
d:\abc\data.txt
baidu_read_data.py
#coding=utf-8
from selenium import webdriver
import os,time
source= open("D:\\abc\\data.txt", "r")
values = source.readlines()
source.close()
# 執行循環
for serch in values:
browser =webdriver.Firefox()
browser.get("http://www.baidu.com")
browser.find_element_by_id("kw").send_keys(serch)
browser.find_element_by_id("su").click()
browser.quit()
這裏簡單說明一下,open方法左以只讀方式(r)打開本地的 data.txt 文件,readlines
方法是逐行的讀取文件內容。
經過 for 循環,serch 能夠每次獲取到文件中的一行數據,在定位到百度的輸入框後,
博客園 — 蟲師
http://fnng.cnblogs.com 86
將數據傳入 send_keys(serch)。這樣經過循環調用,直到文件的中的全部內容全被讀取。
27.2 、用戶名密碼的參數化(讀取文件)
按照上面的方法,對自動化腳本中用戶名密碼進行參數化應該很簡單,其實沒有想象的
那麼簡單,從目前我所查到 python 讀取方法有,整個文件讀取,逐行讀取,固定字節讀取。
怎樣才一次讀取用戶名和密碼兩個信息呢,最初的修改是這樣的:
建立兩個文件,分別存放用戶名密碼
調用用戶名密碼登陸登陸的腳本
#coding=utf-8
from selenium import webdriver
import os,time
source= open("D:\\abc\\data2.txt", "r") #用戶名文件
user = source.read(5) #用戶名長度
source.close()
source2 = open("D:\\abc\\data3.txt", "r") #密碼文件
pw =source2.read(6) #密碼長度
source2.close()
driver = webdriver.Firefox()
driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fwebcloud.kuaibo.com%2
F")
driver.find_element_by_id("user_name").clear()
driver.find_element_by_id("user_name").send_keys(user)
time.sleep(3)
driver.find_element_by_id("user_pwd").clear()
driver.find_element_by_id("user_pwd").send_keys(pwd)
time.sleep(3)
博客園 — 蟲師
http://fnng.cnblogs.com 87
driver.find_element_by_name("Submit").click()
time.sleep(1)
driver.quit()
缺點:
雖然目的達到了這,但這樣的實現有不少問題:
一、用戶名密碼分別在不一樣的文件裏,這樣就要求用戶名密碼必須一一對應
二、必須指定讀取的長度,測試 readlines() 並非讀取的一行數據。
三、沒法循環讀取。
27.3 、用戶名的參數化(字典)
用戶名密碼參數化
解決循環調用
經過一成天研究,從新補習 python 字典、函數調用,若是固定只是讀取用戶名,密碼
兩個值,能夠經過以下方法實現。
建立 fun.py 文件,定義一個字典方法:
def zidian():
d={'fnngj':'a23456','testing360':123456}
print "suess read usernameand password!!"
return d
字典的能夠方便的存放 k,v鍵值對,一個鍵對應一個值;注意,若是密碼中有非數字,
須要加單引號。
下面循環調用詞典的值:
#coding=utf-8
from selenium import webdriver
import os,time
import fun #導入函數
博客園 — 蟲師
http://fnng.cnblogs.com 88
#循環調用字典裏的用戶名密碼,分別賦值給 k,v
for k,v in fun.zidian().items():
driver = webdriver.Firefox()
driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fwebcloud.kuaibo
.com%2F")
driver.find_element_by_id("user_name").clear()
driver.find_element_by_id("user_name").send_keys(k)
time.sleep(3)
driver.find_element_by_id("user_pwd").clear()
driver.find_element_by_id("user_pwd").send_keys(v)
time.sleep(3)
driver.find_element_by_id("dl_an_submit").click()
time.sleep(1)
driver.close()
腳本這樣表設計就穩定了不少,每次取的值很是固定,並且一樣實現了參數與腳本分離,
若是幾百個腳本都調用 fun( ) 函數,當須要修改用戶名密碼時,只用修改 fun( )函數裏面字
典的值就能夠了。
27.4 、用戶名密碼的參數化(函數)
其實,在個人項目中只須要作到參數化就好了,並不須要循環的讀取內容。那麼經過函
數調用就能夠很簡單的解決。
fun.py
def user(k='fnngj',v=123456):
print "suess read username and password!!"
return k,v
賦默認值,並將結果返回。
調用函數值:
#coding=utf-8
博客園 — 蟲師
http://fnng.cnblogs.com 89
from selenium import webdriver
import os,time
import fun #導入函數
#經過調用函數得到用戶名&密碼
k,v = fun.user()
print k,v
driver = webdriver.Firefox()
driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fwebcloud.kuaibo
.com%2F")
driver.find_element_by_id("user_name").clear()
driver.find_element_by_id("user_name").send_keys(k)
driver.find_element_by_id("user_pwd").clear()
driver.find_element_by_id("user_pwd").send_keys(v)
driver.find_element_by_id("dl_an_submit").click()
time.sleep(3)
driver.close()
運行結果:
>>> =================== RESTART ================================
>>>
suess read username and password!!
fnngj 123456
.
----------------------------------------------------------------------
Ran 1 test in 25.484s
OK
博客園 — 蟲師
http://fnng.cnblogs.com 90
若是學好了 python 語言,解決問題的方法是多樣的,使用最貼合需求的方法,簡單解
決問題。這一節寫的比較多,對構建自動化框架來講,參數化是很是重要的一個知識點。
二十8、測試套件
在 23 章單元測試框架解析中我提了到「測試套件」,當時只是把一個.py 文件裏的多個
用例經過測試套件執行。批量執行測試集中 雖然能夠批量執行多個.py 文件,但它使用的
是讀取文件夾下文件的方式,而不是使用的測試套件。這一節就使用測試套件來執行多個.py
測試文件。
最終咱們全經過測試套件完成下面的結構:
測試套件的問題解決了,26 章生成測試報告遺留的問題天然也能夠解決了。
28.1 、測試套件實例
下面經過一個例子來組建咱們的測試套件。
test_youdao.py
#coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
博客園 — 蟲師
http://fnng.cnblogs.com 91
from selenium.webdriver.support.uiimport Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
import HTMLTestRunner
class Youdao(unittest.TestCase):
def setUp(self):
self.driver =webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com"
self.verificationErrors = []
self.accept_next_alert = True
#百度搜索用例
def test_youdao_search(self):
driver = self.driver
driver.get(self.base_url +"/")
try:
driver.find_element_by_id("query").send_keys(u"蟲師")
driver.find_element_by_id("qb").click()
time.sleep(2)
except:
driver.get_screenshot_as_file("D:\\selenium_use_case\\error_png\\kw.png")
#若是沒有找到上面的元素就截取當前頁面。
def tearDown(self):
self.driver.quit()
博客園 — 蟲師
http://fnng.cnblogs.com 92
self.assertEqual([], self.verificationErrors)
if__name__ == "__main__":
suite = unittest.TestSuite()
suite.addTest(Youdao("test_youdao_search"))
#這裏能夠添加更多的用例,如:
#suite.addTest(Youdao("aaaa"))
unittest.TextTestRunner().run(suite)
test_baidu.py
#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.uiimport Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
import HTMLTestRunner
class Baidu(unittest.TestCase):
def setUp(self):
self.driver =webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com"
self.verificationErrors = []
self.accept_next_alert = True
博客園 — 蟲師
http://fnng.cnblogs.com 93
#百度搜索用例
def test_baidu_search(self):
driver = self.driver
driver.get(self.base_url +"/")
try:
#是一個沒法找到的元素 id
driver.find_element_by_id("kw").send_keys("selenium webdriver")
except:
driver.get_screenshot_as_file("D:\\selenium_use_case\\error_png\\kw.png")
#若是沒有找到上面的元素就截取當前頁面。
driver.find_element_by_id("su").click()
time.sleep(2)
driver.close()
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if__name__ == "__main__":
suite = unittest.TestSuite()
suite.addTest(Baidu("test_baidu_search"))
#一樣的,能夠在這個文件中添加更多的用例。
#suite.addTest(Youdao("aaaa"))
results= unittest.TextTestRunner().run(suite)
經過測試套件運行上面兩個測試文件,建立 all_tests.py 文件
博客園 — 蟲師
http://fnng.cnblogs.com 94
#coding=utf-8
"Combine tests for gnosis.xml.objectify package(req 2.3+)"
import unittest, doctest
import test_baidu, test_youdao #這裏須要導入測試文件
import HTMLTestRunner
suite = doctest.DocTestSuite()
#羅列要執行的文件
suite.addTest(unittest.makeSuite(test_baidu.Baidu))
suite.addTest(unittest.makeSuite(test_youdao.Youdao))
unittest.TextTestRunner(verbosity=2).run(suite)
運行結果:
>>> =========================RESTART ================================
>>>
test_baidu_search (test_baidu.Baidu) ... ok
test_youdao_search (test_youdao.Youdao) ... ok
----------------------------------------------------------------------
Ran 2 tests in 15.140s
OK
28.2 、整合 HTMLTestRunner 測試報告
生成 HTMLTestRunner 報告和前面的方法同樣,只是把代碼移動 all_tests.py 文件便可;
並且只須要在這一個地方生成便可。
下面看加入 HTMTestRunner以後的 all_tests.py 文件
博客園 — 蟲師
http://fnng.cnblogs.com 95
#coding=utf-8
"Combine tests for gnosis.xml.objectify package(req 2.3+)"
import unittest, doctest
#這裏須要導入測試文件(test_baidu.py,test_youdao.py)
import test_baidu,test_youdao
import HTMLTestRunner
suite = doctest.DocTestSuite()
suite.addTest(unittest.makeSuite(test_baidu.Baidu))
suite.addTest(unittest.makeSuite(test_youdao.Youdao))
filename = 'D:\\result20.html'
fp = file(filename, 'wb')
runner=HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='Report_title',
description='Report_description')
runner.run(suite)
代碼都是前面見過的,這裏就不費口舌了再解析了;若是不太理解就多敲幾遍,天然就
理解。運行測試報告以下,這樣再多文件的用例均可以放到一張報告裏了。
博客園 — 蟲師
http://fnng.cnblogs.com 96
28.3 、更易讀的報告
報告已經接近完美了,惟一的一點小瑕疵,這報告若是給領導看的話,哪知道什麼是什
麼,通過 MarkRabbit 的指點,咱們能夠給每個用例加個中文註釋。
............
#百度搜索用例
def test_baidu_search(self):
u"""百度搜索用例"""
driver = self.driver
driver.get(self.base_url +"/")
................
每一個用例(方法)下面均可以加這個一行註釋信息,小 u 是避免中文引發的亂碼問題。
博客園 — 蟲師
http://fnng.cnblogs.com 97
再來跑一下用例,找開生成的報告,是否是完美了,傻瓜都知道是幹嗎的。
二十9、結構改進
到目前爲止問題已經解決了,經過測試套件執行全部用例,測試報告整合,全部文件都
在一個目錄下面,估計用例寫多了,不方便管理,這一章試着調整一下結構。
29.1 、all_tests.py 移出來
all_tests.py 是調用例的程序,而不是執行用例的,因此應該把它移出來。結構上會
更爲合理。
/selenium_use_case/test_case/untie/test_baidu.py
/unite/test_baidu.py
/unite/__init__.py
/unite/...
/all_tests.py
目錄結構應該是這樣的,untie 文件夾下存放具體的執行用例,all_tests.py 應該與 untie
文件夾平級。
另外,須要在 unite 文件夾下放一個__init__.py 文件,文件內容能夠爲空。
那麼直接移出來後再運行 all_tests.py 文件會提示不到測試文件,因此,咱們要對代碼
作調整,把文件夾加到 sys.path 下就能夠找到了。在 all_tests.py 頭部添加如下內容。
.......
博客園 — 蟲師
http://fnng.cnblogs.com 98
import sys
sys.path.append("/selenium_use_case/test_case")
from sutie import test_youdao
from sutie import test_baidu
.....
29.2 、__init__.py 文件解析
all_tests.py 是移出來了,可是還有個問題,導入包(用例文件)也是個問題,假如幾個
用例能夠經過「from sutie import test_xxx」 的方式導入,假如成幾百條呢,這樣羅列幾百
條,作法確實太二;那有沒有不那麼二的方式呢。
還記得上面提到的__init__.py 文件吧,這文件是幹嗎的,爲何要在引用的目錄下加這
個文件?
要弄明白這個問題,首先要知道,python 在執行 import 語句時,到底進行了什麼操做,按照
python 的文檔,它執行了以下操做:
第 1 步,建立一個新的,空的 module 對象(它可能包含多個 module);
第 2 步,把這個 module 對象插入 sys.module 中
第 3 步,裝載 module 的代碼(若是須要,首先必須編譯)
第 4 步,執行新的 module 中對應的代碼。
在執行第 3 步時,首先要找到 module 程序所在的位置,搜索的順序是:
當前路徑 (以及從當前目錄指定的 sys.path),而後是 PYTHONPATH,而後是 python 的安
裝設置相關的默認路徑。正由於存在這樣的順序,若是當前 路徑或 PYTHONPATH 中存在與標準
module 一樣的 module,則會覆蓋標準 module。也就是說,若是當前目錄下存在 xml.py,那麼
執 行 import xml 時,導入的是當前目錄下的 module,而不是系統標準的 xml。
瞭解了這些,咱們就能夠先構建一個 package,以普通 module 的方式導入,就能夠直接訪問
此 package 中的各個 module 了。python 中的 package 必須包含一個__init__.py 的文件。
------以上引用「老王 python」
博客園 — 蟲師
http://fnng.cnblogs.com 99
其實__init__.py 文件中能夠有內容; 咱們在導入一個包時,實際上導入了它的
__init__.py 文件。
在__init__.py 文件中添加導入包
import test_baidu
import test_youdao
而後,all_tests.py 文件但是這樣修改:
.......
import sys
sys.path.append("/selenium_use_case/test_case")
from sutie import *
.....
「*」 星號表示導入 sutie 目錄下的全部文件;在 sutie 目錄下建立測試用例文件,只用
在__init__.py 文件下羅列就能夠了。而對於 all_tests.py 文件來講不須要作任何調整。
29.3 、調用多級目錄的用例
當測試用例達到必定量級的時候,爲了便於管理,一定須要在目錄下面再分目錄。假設
咱們有這樣一個結構:
/selenium_use_case/test_case/untie/test_baidu.py
/unite/test_baidu.py
/unite/sogou/test_sogou.py ----二級測試用例目錄
/unite/sogou/__init__.py
/unite/sogou/...
/unite/__init__.py
/unite/...
/all_tests.py
其實,這個問題也很好處理,接着分析__init__.py 文件,它處了能導入當前目錄下的
博客園 — 蟲師
http://fnng.cnblogs.com 100
文件,是否是還能夠導入其它目錄下包,或者模塊。假設在/unite/sogou/目錄下建立了
test_sogou.py 測試文件,修改 unite 目錄__init__.py 文件:
#coding=utf-8
import sys
sys.path.append("/selenium_use_case/test_case/sutie")
from sogou import *
import test_baidu
import test_youdao
別忘了/unite/sogou/ 目錄下也要加__init__.py 文件,而且加入包。掌握的這個技巧,再
也不用擔憂多級目錄的問題了。
29.4 、改進用例的讀取
你覺得這樣就算完了麼? 還有個更嚴峻的問題須要處理,若是你夠警覺必定注意
all_tests.py 的這段代碼:
....
suite = doctest.DocTestSuite()
suite.addTest(unittest.makeSuite(test_baidu.Baidu))
suite.addTest(unittest.makeSuite(test_youdao.Youdao))
suite.addTest(unittest.makeSuite(test_sogou.Sogou))
.....
對的,這也是沒法迴避的一個硬傷,跟導入包同樣沒法避免,想一想成百的用例羅列到這
裏是多麼痛的領悟。。
最早想到的是能不能經過一個循環來解決掉這個問題,循環的讀取某個目錄下的全部文
件;若是你還記得本文檔的 第 24章 章 有一個叫 test_case_.py 的文件的話,讀取某個文件夾
下的全部文件是一件很簡單的事情;可是如何將結果生成到報告裏呢。解決這個問題仍是稍
微有那麼一點兒難度的。
通過改進的新 all_tests.py 代碼以下:
博客園 — 蟲師
http://fnng.cnblogs.com 101
#coding=utf-8
import sys ,re ,os,math
sys.path.append("/selenium_use_case/test_case")
from sutie import *
import unittest, doctest ,site
import HTMLTestRunner
#將用例組建成數組
alltestnames = [
'sutie.test_baidu.Baidu',
'sutie.test_youdao.Youdao',
'sutie.sogou.test_sogou.Sogou', #注意這個用例是二級目錄下的
]
suite =unittest.TestSuite()
if __name__== '__main__':
# 這裏咱們可使用 defaultTestLoader.loadTestsFromNames(),
# 但若是不提供一個良好的錯誤消息時,它沒法加載測試
# 因此咱們加載全部單獨的測試,這樣將會提升腳本錯誤的肯定。
fortest inalltestnames:
try:
#最關鍵的就是這一句,循環執行數據數的裏的用例。
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(test))
except Exception:
print 'ERROR: Skipping tests from "%s".' % test
try:
__import__(test)
except ImportError:
print 'Could not importthetest module.'
else:
print 'Could not load the test suite.'
from traceback import print_exc
print_exc()
print
print 'Running the tests...'
filename = 'D:\\result21.html'
博客園 — 蟲師
http://fnng.cnblogs.com 102
fp = file(filename,'wb')
runner =HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='Report_title',
description='Report_description')
runner.run(suite)
代碼解析,爲了作到只解決當前面的問題,上面的代碼作了不少簡化。其實,咱們能夠
在這裏完成更多的功能。
首先咱們以「目錄.用例文件.用例類」的格式將用例放到一個數組中,能夠這樣作的前
提是咱們導入了測試用例文件;而後組成了 alltestnames 數組。
經過一個 for 循環來讀取數組的內容;讀取的方法是:
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(test))
緊接的 try...except... 是對異常的處理,若是不理解,能夠暫無視或刪除異常捕捉
的相關代碼,使代碼更清爽。
下面的代碼已經見過好屢次了,是用於生成 HTMLTestRunner 報告的。
29.5 、進一步分離用例列表
都到進一步分,下面知道該怎麼作了吧!? 翻一下 第 27.3節 節 參數化中的字典,應該能
找到方法。都把用例組成數組了,咱們要作的就是把它放到一個單獨的文件裏。
建立 allcase_list.py 文件,與 all_tests.py 在同一級目錄下。把數組放到一個方法
裏,allcase_list.py 內容以下:
def caselist():
alltestnames = [
'sutie.test_baidu.Baidu',
'sutie.test_youdao.Youdao',
'sutie.sogou.test_sogou.Sogou',
]
print "suess read case list success!!"
博客園 — 蟲師
http://fnng.cnblogs.com 103
return alltestnames
在 all_tests.py 中進行調用:
#coding=utf-8
....
import allcase_list #調用數組文件
#獲取數組方法
alltestnames = allcase_list.caselist()
...
suite =unittest.TestSuite()
if __name__== '__main__':
fortest inalltestnames:
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(test))
.....
如今如今優雅多了,把須要的執行的用例往 allcase_list.py 的數組是羅列就好了。
用例的調整,all_tests.py 文件不須要作任何的修改。
最後再回顧一下咱們有目前測試的目錄結構:
/selenium_use_case/test_case/untie/test_baidu.py -----一級目錄測試用例
/unite/test_baidu.py
/unite/sogou/test_sogou.py ----二級目錄測試用例目錄
/unite/sogou/__init__.py
/unite/sogou/...
/unite/__init__.py
/unite/...
/all_tests.py ----調用全部腳本執行
/allcase_list.py -----羅列要執行的用例
/test_result/result1.html ----測試報告的存入目錄
博客園 — 蟲師
http://fnng.cnblogs.com 104
目前看上去還不錯的樣子~!(得意笑),可是咱們項目不一樣,需求不一樣,或者當用例達
到必定量級後,還會有不少問題暴露出來,須要咱們一一的去解決;好吧~!第三版的內容
就到這裏了。
三10、UliPad--python 開發利器
工欲善其事,必先利其器
有時候每每選擇太多,變得無從選擇。若是你在 python 開發中已經找到了趁手的 IDE這
一節能夠無視。
其實,pyhon下面能找到一款不錯的開發工具是不太容易的。
IDLE 寫寫單個小程序很好,但一個程序文件與執行信息是兩個窗口,程序開多了就分
不清哪一個了。
pythonWin 也用過,窗口有些老土,窗口布局我不會設置,因此以爲也很差用。
notepad++ 這種小巧的萬能編輯器,偶爾用用還行。
x linux 會有一些很是不錯的交互式python IDE ,如 ipython、bpython 等。
m vim 確定是開發神器,但通常也只有高手纔會運用自如,體會它的奧妙。
UliPad 是找到的寫 python 最舒服的一個 IDE 。
地址: https://code.google.com/p/ulipad/
免費,能夠免費得到並使用它的全部功能。
支持 windows 、MAC、linux 等平臺。
小巧,內存佔用不多,10MB 左右。
博客園 — 蟲師
http://fnng.cnblogs.com 105
具體,的安裝使用,這裏就不介紹了,不是本文檔的主題。有興趣使用能夠參考個人博客:
http://www.cnblogs.com/fnng/p/3393275.html
另外,還有一些很是棒的收費 python IDE
Wing IDE4.1
http://wingware.com/
pycharm
http://www.jetbrains.com/pycharm/
但願這一節沒影響到文檔的和諧。呵呵~!
博客園 — 蟲師
http://fnng.cnblogs.com 106
後記:
都在談自動化測試,自動化測試是「部分」功能測試的一種替代技術(它們比例確定在
逆轉)。經過學習自動腳本也可使測試人員突破不懂代碼的限制;而自動化腳本入門簡單。
我以爲自動化是方向。
關於自動化又幫了你一段路,可是,依然還有不少問題沒有解決;好比,測試用例的多
線程處理。目前的結構還不夠完美,在腳本運行中,咱們能夠捕捉更多的信息,更容易的定
位問題;使咱們的結構更靈活的適應需求的變化;路還很長,任重道遠,一塊兒加油吧!
這些問題依然不是一份學習文檔能夠解決的,若是你掌握了本文檔的全部內容,建議從
如下幾個方面來提升本身的自動化測試水平:
python 語言:兔子(它不讓叫兔子了,叫 t MarkRabbit )的話清晰的說明了學習自動
化測試的思路:咱們須要用 python 這門語言去調用 selenium 的一些工具來操做瀏覽器,
幫助咱們實現「web UI 」自動化。因此,咱們的重心應該放在語言自己的學習。後面這幾
章解決問題用的也是 python 技術。
Javascript 語言:在實際的自動化測試過程當中,咱們會遇到各類問題,有時候 webdriver
提供的方法不能幫咱們解決問題,那麼須要藉助 Javascript 來解決問題。
xpath \css 定位: 不能操做一個元素,不少狀況下是咱們沒辦法定位這個元素;因此要
深刻了解 xpath \css 定位的用法。
擴展資料:
rtsm eyiselenium 與webdriver 的關係:
http://v.qq.com/boke/page/j/v/v/j01135krrvv.html
lazyman 快速入門:
http://v.qq.com/boke/page/i/k/a/i0113wompka.html
關於 python 自動化的博客,慢慢研讀:
博客園 — 蟲師
http://fnng.cnblogs.com 107
http://www.cnblogs.com/hzhida/archive/2012/08/13/2637089.html
splinter 自動化框架:
http://splinter.cobrateam.info/docs/why.html
http://v.qq.com/boke/page/s/8/3/s0114uu1d83.html。
你們能夠了解一下webdriverguide的內容
webdriverAPI地址:
https://github.com/easonhan007/webdriver_guide
robot framework
自動化測試框架,後序研究。
RF框架系列文章
http://www.51testing.com/?21116/
http://blog.csdn.net/tulituqi/article/category/897484/2
安裝:http://blog.sina.com.cn/s/blog_654c6ec70100tkxn.html
selenium webdriver py 文檔
http://selenium.googlecode.com/git/docs/api/py/index.html
r seleniumwrapper 0.5.3
https://pypi.python.org/pypi/seleniumwrapper
selenium webdriver 系列教程
http://blog.csdn.net/nbkhic/article/details/6896889
文檔
http://selenium.googlecode.com/git/docs/api/py/index.html
phantomJSjavascript