1、selenium介紹css
selenium主要用於web應用程序的自動化測試,還支持全部基於web的管理任務自動化。html
selenium經歷了2個版本,selenium1.0和selenium2.0;selenium不是一個單獨的工具,而是由一些插件、類庫構成,每一個組成部分都有其特色和應用場景。前端
selenium2.0由如下組件構成:python
selenium2.0 = selenium1.0 + Webdriverweb
Webdirver:經過原生瀏覽器支持或擴展來直接控制瀏覽器,針對各個瀏覽器開發,與瀏覽器緊密集成,支持建立更高級的測試,其還能夠利用操做系統級的調用,模擬用戶輸入;chrome
selenium IDE:嵌入到Firefox瀏覽器中的一個插件,實現簡單的瀏覽器操做錄製與回放功能,主要用於快速建立BUG及重現腳本,可轉化爲多種語言;編程
selenium Gird:測試輔助工具,利用現有的計算機基礎設施,實現多臺計算上和異構環境中運行測試用例;設計模式
selenium RC:selenium的核心組件,支持多種不一樣語言編寫自動化測試腳本,經過其服務器做爲代理服務器去訪問應用,達到測試的目的;瀏覽器
Client Libraries:Client Libraries庫主要用於編寫測試腳本,用來控制Selenium Server的庫;安全
Selenium Server:負責控制瀏覽器行爲;
Selenium Core(一個JavaScript函數集合):被嵌入到瀏覽器中,經過它實現用程序對瀏覽器進行操做;
Launcher:用於啓動瀏覽器,把Core加載到瀏覽器頁面當中,並把瀏覽器代理設置爲Selenium Server的HTTP Proxy;
2、環境搭建
一、安裝python
登陸Python官網,找到download,選擇與自身平臺(Windows/Linux)相符的版本下載(建議3.5+),而後安裝便可;
注意:安裝時選擇安裝界面的「Add Python 3.x to PATH」進行勾選,避免再次配置環境變量;
安裝完成後經過Windows命令提示符CMD輸入「python」,查看是否安裝成功,以下圖所示:
如上圖所示,則證實安裝成功;
二、安裝setuptools與pip
setuptools是PEAK(Python enterprise Application Kit)的一個副項目,是python的distutilsde的加強工具,能夠更方便建立和發佈python包,特別是對其餘包有依賴的狀況;
pip是一個安裝和管理python包的工具,經過pip來安裝python包將變得很簡單,省去了繁瑣的過程,pip的安裝依賴於setuptools,安裝pip以前須要先安裝setuptools;
注意:python目前不支持setuptools,所以須要使用distribute;
setuptools與pip的下載地址以下:
setuptools:https://pypi.python.org/pypi/setuptools
pip:https://pypi.org/project/pip/
注意: 最新版的python安裝包中已經集成了pip,能夠在安裝目錄下的script路徑下查看是否有pip.exe或pip3.exe文件,若是有,則cmd命令行中輸入pip進行驗證;
如上圖所示,則證實已經安裝pip;
三、安裝selenium
完成上面2個步驟以後,能夠經過cmd命令直接安裝selenium包,以下圖所示:
注意:安裝時若是隻輸入包名,則默認安裝當前庫中的最新版本,若是想安裝本身須要的版本,則須要在包名後面加上版本號,好比:
pip install selenium==2.48.0
四、下載瀏覽器驅動
前面說過,selenium支持多種瀏覽器,因此只須要下載對應的瀏覽器驅動,將解壓獲得的exe文件放到python的安裝目錄下便可;
各個瀏覽器驅動下載地址:https://www.seleniumhq.org/download/
五、調試
打開一款python編譯器,輸入下面的代碼,運行,查看是否成功調用瀏覽器運行,若是運行成功,則說明已成功搭建好自動化開發環境;
1、WebDriver原理
一、關於WebDriver
設計模式:按照Server-Client的經典設計模式設計;
Server端:即Remote Server(遠程服務器),能夠是任意的瀏覽器,當腳本啓動瀏覽器時,該瀏覽器就是Remote Server,它的職責是等待Client發送請求並作出響應;
Client端:簡單來講就是咱們的測試代碼,測試代碼中的一些行爲是以HTTP請求的方式發送給被測試瀏覽器——Remote Server,Remote Server接受請求,執行相應操做,
並在Response中返回執行狀態、返回值等信息;
二、WebDriver工做流程
①WebDriver啓動目標瀏覽器,並綁定至指定端口,啓動的瀏覽器實例將做爲WebDriver的Remote Server;
②Client端經過CommandExcuter發送HTTPRequest給Remote Server的偵聽端口(通訊協議:the webdriver wire protocol);
③Remote Server須要依賴原生的瀏覽器組件(好比:chromedriver.exe)來轉化瀏覽器的native調用;
三、WebDriver.log
python提供了logging模塊給運行中的應用,提供了一個標準的信息輸出接口。它提供了basicConfig方法用於基本信息的定義,開啓debug模塊,
就能夠捕捉到Client端向Server端發送的請求,例子以下:
1 # coding=utf-8 2 # 導入logging模塊,捕捉Client發送的請求 3 from selenium import webdriver 4 import logging 5 from selenium import webdriver 6 from selenium.webdriver.support.select import Select # select類 7 from selenium.webdriver.common.by import By #By類:定位元素 8 9 logging.basicConfig(level=logging.DEBUG) 10 driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") 11 driver.get("www.baidu.com") 12 13 driver.find_element_by_id("kw").send_keys("selenium") 14 driver.find_element_by_id("su").click() 15 driver.quit()
2、WebDriver定位方法
WebDriver是基於selenium設計的操做瀏覽器的一套API,針對多種編程語言都實現了這套API,站在python角度來講,WebDriver是python的一個用於實現Web自動化的第三方庫。
一、WebDriver定位方法
WebDriver定位方法提供了八種元素定位方法,所對應的方法、特性分別是:
二、XPath和CSS的相似功能對比
三、用By定位元素
針對前面介紹的8種定位方法,WebDriver還提供另外一種方法,即:統一調用find_element()方法,經過By來聲明定位方法,而且傳入對應定位方法的定位參數,例子以下:
find.element()方法只用於定位元素,它須要兩個參數,第一個參數是定位的類型,由By提供,第二個參數是定位的具體方式,在使用By以前須要將By類導入;
# 導入By類的包 from selenium.webdriver.common.by import By find.element(by.id,"kw") find.element(by.name,"wd") find.element(by.class_name,"s_ipt") find.element(by.tag_name,"input") find.element(by.link_text,"新聞") find.element(by.partial_link_text,"新") find.element(by.xpath,"//*[@class='bg s_btn'") find.element(by.css_selector,"span.bg s_btn_wr>input#su")
四、定位一組元素
上面提到的8種定位方法,都是針對單個元素定位的,webdriver還提供了與之對應的8種用於定位一組元素的方法。其通常應用於如下場景:
①批量操做元素,例如勾選頁面上全部的複選框;
②先獲取一組元素,再從這組元素中過濾出須要操做的元素;
定位一組元素的方法與定位單個元素的用法類似,惟一的區別是在element後面多一個s表示複數,具體以下:
# webdriver提供的定位一組元素方法 id find_elements_by_id() Name find_elements_by_name() class_name find_elements_by_class_name() tag Name find_elements_by_tag_name() link text find_elements_by_link_text() partial link text find_elements_by_partial_link_text() xpath find_elements_by_xpath() css selector find_elements_by_css_selector()
獲取一組元素中某個元素的幾個方法:
len():用來計算元素的個數,經過print()打印出計算的結果;
pos()或pop(-1):默認獲取一組元素的最後一個元素,並返回該元素的值;
pop(0):默認獲取一組元素的第一個元素,並返回該元素的值;
pop(1):默認獲取一組元素的第二個元素,並返回該元素的值;
......
3、WebElement接口經常使用方法
一般須要與頁面交互的方法都由WebElement接口提供,包括上面提到的8種定位方法,下面介紹經常使用的幾種方法:
submit():用於提交表單,例如搜索框輸入關鍵字以後的「回車」操做,例如:
# 提交表單 from select import webdriver driver = webdriver.Chrome("安裝工具\python\chromedriver.exe") driver.get("http://www.baidu.com") driver.find_element_by_id("kw").send_keys("imyalost") # 提交輸入框中的內容 driver.find_element_by_id("imyalost").submit() driver.quit()
注意:有時候submit()方法和click()方法能夠互用,但submit()的應用範圍不及click()普遍;
clear():清除文本;
send_keys(*value):模擬按鍵輸入;
click():單擊元素;
size:返回元素的尺寸;
text:獲取元素的文本;
get.attribute(name):得到屬性值;
is_displayed():設置該元素是否用戶可見;
# webelement接口經常使用方法 from selenium import webdriver driver = webdriver.Chrome("安裝工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 得到輸入尺寸 size = driver.find_element_by_id("kw").size print("size") # 返回百度頁面底部備案信息 text = driver.find_element_by_id("cp").text print("text") # 返回元素的屬性值,能夠是id、name、type或其餘屬性 attribute = driver.find_element_by_id("kw").get_attribute("type") print("attribute") # 返回元素結果是否可見,返回結果爲True或Flase result = driver.find_element_by_id("kw").is_displayed() print("result")
1、控制瀏覽器
webdriver主要提供操做頁面上各類元素的方法,但它也提供操做瀏覽器的一些方法,例如控制瀏覽器大小、前進和後退等。
一、控制瀏覽器窗口大小
# 控制瀏覽器大小 from selenium import webdriver driver = webdriver.Chrome("安裝工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 參數數字爲像素點 print("設置瀏覽器寬480、高800顯示") driver.set_window_size(480,800)
二、全屏顯示
webdriver提供了maximize_window()方法使打開的瀏覽器全屏顯示,其用法與set_window_size()相同。
三、控制瀏覽器前進、後退
如今的瀏覽器在瀏覽網頁時都提供了前進和後退功能,webdriver也提供了對應的forward()和back()方法,來模擬前進和後退按鈕:
# 控制瀏覽器前進、後退 from selenium import webdriver driver = webdriver.Chrome("安裝工具\python\chromedriver.exe") # 訪問百度首頁 first_url='http://www.baidu.com'' print("now access %s "%(first_url)) driver.get(first_url) # 訪問新聞頁面 second_url='http://www.news.baidu.com' print("now access % s "%(second_url)") driver.get("second_url") # 後退到百度首頁 print("back to %s "%(first_url)") driver.back() # 前進到新聞頁 print("forward to %s "%(second_url)") driver.forward()
爲了看清腳本執行過程,每一步的操做都經過print()打印當前的URL地址,執行結果以下:
now access http://www.baidu.com
now access http://news.baidu.com
back to http://www.baidu.com
froward to http://news.baidu.com
四、模擬瀏覽器前刷新
通常咱們刷新頁面都是經過F5或者頁面上的刷新按鈕,webdriver也提供了刷新方法refresh(),用來模擬頁面刷新:
......
# 刷新當前頁面
driver.refresh()
......
2、鼠標事件
在webelement接口提供的方法中,能夠經過click()來模擬鼠標單擊操做,但實際上鼠標交互方式不少,例如:右擊、懸停、鼠標拖動等功能;
webdriver提供了ActionChains類,封裝了鼠標操做的經常使用方法:
perform():執行全部的ActionChains中存儲的行爲
context_click():鼠標右擊
double_click():鼠標雙擊
drag_and_drop():鼠標拖動
move_to_element():鼠標懸停
一、鼠標右擊操做
# 鼠標右擊操做 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains driver = webdriver.Chrome("安裝工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 定位到要右擊的元素 right_click = driver.find_element_by_id("KW") # 對定位到的元素執行鼠標右擊操做 ActionChains(driver).context_click(right_click).perform() ...
二、鼠標懸停
鼠標懸停彈出下拉菜單也是一個十分常見的功能設計,move_to_element()方法能夠模擬鼠標懸停動做,其用法與context_click()相同;
1 # 鼠標懸停 2 ... 3 above = driver.find_element_by_id("id") 4 ActionChains(driver).move_to_element(above).perform() 5 ...
三、鼠標雙擊操做
double_click()方法用於模擬鼠標雙擊操做;
1 # 鼠標雙擊操做 2 ... 3 double_click = driver.find_element_by_id("id") 4 ActionChains(driver).double_click(double_click).perform() 5 ...
四、鼠標拖放操做
drag_and_drop(source,target)在源元素上按住鼠標左鍵,而後移動到目標元素上釋放;
source:鼠標拖動的源元素
target:鼠標釋放的目標元素
# 定位元素的位置 ... element = driver.find_element_by_id("id") # 定位元素要移動到的目標位置 target = driver.find_element_by_id("xx") # 執行元素的拖放操做 ActionChains(driver).drag_and_drop(element,target).perform() ...
3、鍵盤事件
Keys()類提供了鍵盤上幾乎全部的按鍵方法,send_keys()不見能夠模擬鍵盤輸入,還能夠用來輸入鍵盤上的按鍵,甚至是組合鍵,例子以下:
# 模擬鍵盤事件 from selenium import webdriver # 引入keys模塊 from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome("安裝工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 輸入框輸入內容 driver.find_element_by_id("kw").send_keys("selenium") # 輸入「教程」 driver.find_element_by_id("kw").send_keys("教程") # 刪除「教程」 driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) ...
如下爲經常使用的鍵盤操做:
# 經常使用的鍵盤操做 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') send_keys(Keys.CONTROL,'v') send_keys(Keys.CONTROL,'x') send_keys(Keys.F1) ... send_keys(Keys.F12)
以上爲webdriver的控制瀏覽器操做以及模擬鍵盤、鼠標操做的經常使用方法,固然具體在實際使用過程當中,還須要結合實際的業務場景,靈活運用
在編寫自動化測試腳本時,爲了使「機器」去自動辨識test case的執行結果是True仍是False,通常都須要在用例執行過程當中獲取一些信息,來判斷用例的執行時成功仍是失敗。
判斷成功失敗與否,就涉及到斷言。webdriver的斷言使用有三種模式:操做(action)、輔助(accessors)、斷言(assertion)。
一、操做(action)
模擬用戶與Web應用程序的交互,通常用於操做應用程序的狀態;
如點擊連接,選擇選項的方式進行工做;若是一個動做執行失敗,或是有錯誤,當前的測試將會中止執行。
常見命令以下:
open(打開頁面)
click(點擊)
clickAndWait(點擊並等待)
type(文本類型)
select(選擇下拉菜單)
selectWindow(選擇彈出窗口)
pause(等待指定時間,以毫秒爲單位,即要睡眠的時間)
setSpeed(設定執行速度。以毫秒延遲間隔長度。默認沒有延遲,即爲0)
setTimeout(指定等待動做完成的等待時間。默認爲30秒,須要等待的動做包括了OPEN 和WAITFOR)
goBack(模擬用戶點擊其瀏覽器上的「back」按鈕)
close(模擬用戶點擊彈出窗體或表單標題欄上的」關閉」按鈕)
二、輔助(accessors)
輔助工具,用於檢查應用程序的狀態並將結果存儲到變量中;
如:storeElementPresent(locator,variableName)
其中參數locator表示元素定位器,variableName用於存儲結果的變量名;
即將locator定位到的狀態存儲到variableName變量中,若是該元素出現返回true,不然返回false,可同斷言一同使用。
三、斷言(assertion)
驗證應用程序的狀態是否同所指望的一致。
常見的斷言包括:驗證頁面內容,如標題是否爲X或當前位置是否正確,或是驗證該複選框是否被勾選。
經常使用斷言以下:
assertLocation(判斷當前是在正確的頁面)
assertTitle(檢查當前頁面的title是否正確)
assertValue(檢查input的值, checkbox或radio,有值爲」on」無爲」off」)
assertSelected(檢查select的下拉菜單中選中是否正確)
assertSelectedOptions(檢查下拉菜單中的選項的是否正確)
assertText(檢查指定元素的文本)
assertTextPresent(檢查在當前給用戶顯示的頁面上是否有出現指定的文本)
assertTextNotPresent(檢查在當前給用戶顯示的頁面上是否沒有出現指定的文本)
assertAttribute(檢查當前指定元素的屬性的值)
assertTable(檢查table裏的某個cell中的值)
assertEditable(檢查指定的input是否能夠編輯)
assertNotEditable(檢查指定的input是否不能夠編輯)
assertAlert(檢查是否有產生帶指定message的alert對話框)
waitForElementPresent (等待檢驗某元素的存在,爲真時,則執行)
使用斷言的注意點:
①不要使用斷言做爲公共方法的參數檢查,公共方法的參數永遠都要執行;
②斷言語句不能夠有任何邊界效應,不要使用斷言語句去修改變量和改變方法的返回值;
在UI自動化測試中,有時候會遇到頁面元素沒法定位的問題,包括xpath等方法都沒法定位,是由於前端元素被設置爲不可見致使。
一、具體問題
常見的頁面元素不可見致使的不可定位,都是因爲下面的問題:
經過查看相關文檔,能夠看出display:none方法是設置元素不可見,這就是致使爲何經過定位頁面元素沒法定位的緣由。
二、解決方案
對於這種問題,能夠經過JavaScript修改頁面元素屬性來將元素置位可見,而後經過id、classname等方法去定位,示例代碼以下(針對上圖所示):
js = "document.getElementById(\"txtPassword\").style.display='block';" # 調用js腳本 driver.execute_script(js) sleep(3) driver.find_element_by_id("txtPassword").send_keys("123456")
代碼解析:
首先經過selenium封裝好的方法document去找到display元素,document提供如下方法來定位display元素:
getElementById():返回對指定ID第一個對象的引用
getElementsByName() :返回帶有指定名稱的對象集合
getElementsByTagName():返回帶有指定標籤名的對象集合
上面我定義了一個js變量,而後經過getElementById()方法去引用display元素,修改none屬性爲block屬性(做爲塊級元素顯示),而後經過selenium自帶的execute_script方法執行腳本。
最後,當元素屬性置爲可見時,能夠經過ID去定位元素。
其實還有一個解決方案:讓前端修改display:none爲block就行了,但這樣的話,帶來的變化和安全風險又是須要考慮的問題。一個問題的解決老是伴隨着新的問題,核裂變了解一下?
想起今天和同行聊天時提及的分裂BUG的話題,對話以下:
大佬N:核裂變的原理是經過中子撞擊原子核產生多個新的原子核,原子核是已有的BUG,中子是修改BUG加上的代碼,分裂以後這個bug消失了,取而代之的是更多的原子核(BUG)。。。
我:引發一個BUG的緣由多是多個,修改一段代碼可能形成多個BUG,就像用新技術解決舊問題而帶來的新問題一個意思。。。
自動化自己最大的挑戰仍是變化,所以從分層測試角度結合公司項目具體狀況,考慮解決問題的方法,纔是最好的選擇。
在利用selenium進行UI自動化測試過程當中,常常會遇到下拉框選項,這篇博客,就介紹下如何利用selenium的Select模塊來對標準select下拉框進行操做。。。
首先導入Select模塊:
1 # coding=utf-8 2 from selenium import webdriver 3 from selenium.webdriver.support.select import Select
感興趣的能夠將鼠標指向Select,而後按住Ctrl鼠標單擊,查看Select模塊的源碼,是如何定義封裝Select的各個方法的。
一、Select提供了三種選擇某一項的方法
1 select_by_index # 經過索引定位 2 select_by_value # 經過value值定位 3 select_by_visible_text # 經過文本值定位
注意事項:
index索引是從「0」開始;
value是option標籤的一個屬性值,並非顯示在下拉框中的值;
visible_text是在option標籤中間的值,是顯示在下拉框的值;
二、Select提供了三種返回options信息的方法
1 options # 返回select元素全部的options 2 all_selected_options # 返回select元素中全部已選中的選項 3 first_selected_options # 返回select元素中選中的第一個選項
注意事項:
這三種方法的做用是查看已選中的元素是不是本身但願選擇的:
options:提供全部選項的元素列表;
all_selected_options:提供全部被選中選項的元素列表;
first_selected_option:提供第一個被選中的選項元素;
三、Select提供了四種取消選中項的方法
1 deselect_all # 取消所有的已選擇項 2 deselect_by_index # 取消已選中的索引項 3 deselect_by_value # 取消已選中的value值 4 deselect_by_visible_text # 取消已選中的文本值
注意事項:
在平常的web測試中,會常常遇到某些下拉框選項已經被默認選中,這種時候就須要用到這裏所說的四種方法;
下面以實際的代碼來作個示例,被測試網頁與源碼截圖以下:
好比要選擇3線,那麼三種選擇方法示例代碼以下:
# coding=utf-8 from selenium import webdriver from selenium.webdriver.support.select import Select from time import sleep # 登陸 driver = webdriver.Chrome() ...... # 根據索引選擇 Select(driver.find_element_by_name("storeDeclare.cityLine")).select_by_index("3") # 根據value值選擇 Select(driver.find_element_by_name("storeDeclare.cityLine")).select_by_value("3線") # 根據文本值選擇 Select(driver.find_element_by_name("storeDeclare.cityLine")).select_by_visible_text("3線") sleep(5) driver.quit()
以上就是關於selenium的Select模塊提供的幾種方法的用法,示例代碼只是示例,具體實踐還須要結合實際的工做須要來進行
UI自動化測試,大多都是經過定位頁面元素來模擬實際的生產場景操做。但在編寫自動化測試腳本中,常常出現元素定位不到的狀況,究其緣由,無非兩種狀況:一、有frame;二、沒有設置等待。
由於代碼運行速度和瀏覽器加載渲染速度,不是一個量級,因此致使了這種狀況發生。webdriver提供了3種類型的等待:顯式等待、隱式等待、強制等待。
一、顯示等待
定義:等待某個條件成立時繼續執行,不然在達到最大時長時拋出異常(TimeoutException);
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None) driver:瀏覽器驅動 timeout:最長超時時間 poll_frequency:檢測間隔時間,默認0.5s ignored_exceptions:超時後的異常信息,默認狀況拋出NoSuchElementException異常 WebDriverWait()通常由until()或until_not方法配合使用,下面是這兩種方法的說明: until(method,message=''):調用該方法提供的驅動程序做爲一個參數,直到返回值爲True; until_not(method,message=''):調用該方法提供的驅動程序做爲一個參數,直到返回值爲Flase;
示例代碼以下:
# coding = utf-8 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") driver.implicitly_wait(10) driver.get('http://www.cnblogs.com/imyalost/') locator = (By.LINK_TEXT, '老_張') try: WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator)) print(driver.find_element_by_link_text('老_張').get_attribute('href')) finally: driver.close()
代碼解析:
本例中,經過as關鍵字將expected_conditions重命名爲EC,並調用presence_of_element_located()方法判斷元素是否存在;
上面的例子中,同時使用了隱性等待和顯性等待,可是須要注意的是:等待的最長時間取二者之中的最大值;
title_is: 判斷當前頁面的title是否徹底等於(==)預期字符串,返回布爾值 title_contains : 判斷當前頁面的title是否包含預期字符串,返回布爾值 presence_of_element_located : 判斷某個元素是否被加到了dom樹裏,並不表明該元素必定可見 visibility_of_element_located : 判斷某個元素是否可見. 可見表明元素非隱藏,而且元素的寬和高都不等於0 visibility_of : 跟上面的方法作同樣的事情,只是上面的方法要傳入locator,這個方法直接傳定位到的element就行了 presence_of_all_elements_located : 判斷是否至少有1個元素存在於dom樹中。舉個例子,若是頁面上有n個元素的class都是‘column-md-3‘,那麼只要有1個元素存在,這個方法就返回True text_to_be_present_in_element : 判斷某個元素中的text是否 包含 了預期的字符串 text_to_be_present_in_element_value : 判斷某個元素中的value屬性是否 包含 了預期的字符串 frame_to_be_available_and_switch_to_it : 判斷該frame是否能夠switch進去,若是能夠的話,返回True而且switch進去,不然返回False invisibility_of_element_located : 判斷某個元素中是否不存在於dom樹或不可見 element_to_be_clickable : 判斷某個元素中是否可見而且是enable的,這樣的話才叫clickable staleness_of : 等某個元素從dom樹中移除,注意,這個方法也是返回True或False element_to_be_selected : 判斷某個元素是否被選中了,通常用在下拉列表 element_selection_state_to_be : 判斷某個元素的選中狀態是否符合預期 element_located_selection_state_to_be : 跟上面的方法做用同樣,只是上面的方法傳入定位到的element,而這個方法傳入locator alert_is_present : 判斷頁面上是否存在alert
二、隱式等待
定義:經過設定的時長等待頁面元素加載完成,再執行下面的代碼,若是超過設定時間還未加載完成,則繼續執行下面的代碼(注意:在設定時間內加載完成則當即執行下面的代碼);
隱式等待的方法爲:implicitly_wait,示例代碼以下:
# coding = utf-8 from selenium import webdriver driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") driver.implicitly_wait(10) # 隱性等待,最長等10秒 driver.get('http://www.cnblogs.com/imyalost/') print(driver.current_url) driver.quit()
代碼解析:
本例中,設置的等待時長爲10秒,但這10秒並不是一個固定時間,並不影響腳本執行速度;其次,隱式等待對整個driver的週期都起做用,所以只須要設置一次便可。
三、強制等待
即sleep()方法,由python中的time模塊提供,強制讓代碼等待xxx時間,不管前面的代碼是否執行完成或者還未完成,都必須等待設定的時間。
示例代碼以下:
# coding = utf-8 from selenium import webdriver from time import sleep driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") driver.get('http://www.cnblogs.com/imyalost/') sleep(5) print(driver.current_url) driver.quit()
代碼解析:
本例中,設置強制等待時間爲5秒,5秒以後,打印獲取到的當前頁面的url,而後關閉窗口。
這種強制等待的方法,在debug時候頗有用,不過建議慎用這種方法,由於太死板,嚴重影響程序執行速度!
以上三種等待方法,在具體的場景中須要根據狀況選擇合適的方法,靈活運用。。。
自動化測試過程當中,得到用例的執行結果後,須要有具象化、簡潔明瞭的測試結果,好比:用例執行時間、失敗用例數、失敗的緣由等,這時候,就須要用到測試報告。
HTML測試報告是python語言自帶的單元測試框架,其擴展的HTMLTestRunner模塊可用於生成易於使用的HTML測試報告。
一、HTMLTestRunner下載
下載地址:http://tungwaiyip.info/software/HTMLTestRunner.html
下載完成後,將下載的文件保存到C盤的\Python35\Lib目錄下(能夠經過以下命令獲取python安裝目錄):
①進入cmd命令行
②輸入python
③輸入import sys
④輸入print(sys.path)
C:\Users\dell>python Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> print(sys.path) ['', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35\\python35.zip', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35\\DLLs', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35\\lib', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35', 'C:\\Users\\dell\\ AppData\\Local\\Programs\\Python\\Python35\\lib\\site-packages']
二、修改HTMLTestRunner文件
由於HTMLTestRunner是基於python2開發的,爲了使其支持python3的環境,須要對其中的部份內容進行修改,修改後的內容以下:
# HTMLTestRunner修改內容 # 第94行 import io # 第539行 self.outputBuffer = io.StringIO() # 第631行 print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)) # 第642行 if not cls in rmap: # 第766行 uo = o # 第772行 ue = e
三、python文件執行與調用
①python文件的後綴爲.py
②py文件既能夠用來執行,就像一小段程序,也能夠用來做爲模塊被導入
③在python中導入模塊通常用import
代碼以下:
from selenium import webdriver import unittest import time class MyTest(unittest.TestCase): def setUp(self): self.driver = webdriver,Chrome("F:\安裝工具\python\chromedriver.exe") self.driver.maximize_window() self.driver.implicitly.wait(10) self.base_url = "http://www.baidu.com" def test_baidu(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_key("unittest") driver.find_element_by_id("su").click() time.sleep(2) title = assertEqual(title,"unittest_百度搜索") def tearDown(self): self.driver.quit() if __name__ == "__main__": unittest.main()
四、HTMLTestRunner測試報告
以上面的test_baidu.py文件爲例子,生成HTMLTestRunner測試報告,代碼以下:
from selenium import webdriver import unittest from HTMLTestRunner import HTMLTestRunner class Baidu(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") self.driver.implicitly_wait(10) self.base_url = "http://www.baidu.com/" def test_baidu_search(self): driver = self.driver driver.get(self.base_url) driver.find_element_by_id("kw").send_key("HTMLTestRunner") driver.find_element_by_id("su").click() def tearDown(self): self.driver.quit() if __name__ == "__main__": baidu = Baidu("test_baidu_search") testunit = unittest.TestSuite() testunit.addTest(baidu) # 定義報告存放路徑 fp = open('./result.html', 'wb') # 定義測試報告 runner = HTMLTestRunner(stream=fp, title='百度搜索測試報告', description= '用例執行狀況:') runner.run(testunit) #運行測試用例 fp.close() #關閉報告文件
代碼簡析:
①將HTMLTestRunner模塊用import導入
②經過open()方法以二進制寫模式打開當前目錄下的result.html,若是沒有則自動建立該文件
③調用HTMLTestRunner模塊下的HTMLTestRunner類,stream指定測試報告文件,title用於定義測試報告的標題,description用於定義測試報告的副標題
④經過HTMLTestRunner的run方法運行測試套件中所組裝的測試用例,最後經過close()關閉測試報告文件
隨着軟件不斷迭代功能愈來愈多,對應的測試用例也會呈指數增加。一個實現幾十個功能的項目,對應的用例可能有上百個甚至更多,若是所有集成在一個文件中,那麼這個文件就很臃腫且維護麻煩。
一個很好的方法就是將這些用例按照功能類型進行拆分,分散到不一樣測試文件中,即一個項目,對應多個分支。
1、分拆後的實現代碼
一、testbaidu.py
from selenium import webdriver import unittest import time class MyTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") self.driver.maximize_window() self.driver.implicitly.wait(10) self.base_url = "http://www.baidu.com" def test_baidu(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_key("unittest") driver.find_element_by_id("su").click() time.sleep(2) title = assertEqual(title,"unittest_百度搜索") def tearDown(self): self.driver.quit()
二、testyoudao.py
from selenium import webdriver import unittest import time class Mytest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("F:\安裝工具\python\chromedriver.exe") self.driver.maximize_window() self.driver.implicitly_wait(10) self.base_url = "http://www.youdao.com" def test_youdao(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("query").clear() driver.find_element_by_id("query").send.keys("webdriver") driver.find_element_by_id("qb").click() time.sleep(2) title = driver.title self.assertEqual(title, "webdriver - 有道搜索") def tearDown(self): self.driver.close()
2、建立用於執行全部用例的ALL_HTMLtest.py文件
一、ALL_HTMLtest.py
# coding=utf-8 import unittest import time from HTMLTestRunner import HTMLTestRunner # 加載用例testbaidu,testyoudao import testbaidu import testyoudao # 將測試用例添加到測試集中 suite = unittest.TestSuite() suite.addTest(testbaidu.MyTest("test_baidu")) suite.addTest(testyoudao.Mytest("test_youdao")) if __name__ == '__main__': # 執行測試 runner = unittest.TextTestRunner() runner.run(suite)
拆分帶來的好處顯而易見,能夠根據不一樣功能建立不一樣的測試文件,甚至不一樣的目錄,還能夠將不一樣的小功能劃分爲不一樣的測試類,在類下編寫測試用例,總體結構更加清晰。
但依然存在缺陷(當用例達到成百上千條時,在ALL_HTMLtest.py中addTest()添加測試用例就變得很麻煩)。。。
二、TestLoader類
unittest單元測試框架提供了TestLoader類,該類負責根據各類標準加載測試用例,並將它們返回給測試套件。
unittest提供了能夠共享的defaultTestLoader類,可使用其子類和方法建立實例,discover()方法就是其中之一。
discover(start_dir, pattern='test*.py', top_level_dir=None)
找到指定目錄下的全部測試模塊,並遞歸查找子目錄下的測試模塊,只有匹配到文件名才能被加載,若是啓動的不是頂層目錄,則頂層目錄必須單獨指定。
start_dir:要測試的模塊名或測試用例目錄;
pattern='test*.py':表示用例文件名的匹配原則,下面的例子中匹配文件名爲以「test」開頭的「.py」文件,星號「*」表示任意多個字符;
top_level_dir=None:測試模塊的頂層目錄,若是沒有頂層目錄,默認爲None;
# coding=utf_8 import unittest from unittest import defaultTestLoader # 定義測試用例的目錄爲當前目錄 test_dir = './' discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py') if __name__ == '__main__': runner = unittest.TextTestRunner() runner.run(discover)
3、集成測試報告
# coding=utf_8 import unittest import time from unittest import defaultTestLoader from HTMLTestRunner import HTMLTestRunner # 定義測試用例的目錄爲當前目錄 test_dir = './report' discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py') if __name__ == '__main__': now = time.strftime("%Y-%m-%d %H_%M_%S") filename = test_dir + '/' + now + 'result.html' fp = open(filename, 'wb') runner = HTMLTestRunner(stream=fp,title='集成測試報告demo',description= '用例執行狀況:') runner.run(discover) fp.close()
執行後,結果以下:
轉載: https://www.cnblogs.com/imyalost