Web頁面組成-代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>python_web頁面_20200226</title>
</head>
<body>
<input type="text" readonly placeholder="請輸入你的名字"></input>
喜歡的歌手:
<input type="checkbox">蕭亞軒</input_type>
<input type="checkbox" checked>鄧麗君</input_type>
<input type="checkbox">毛不易</input_type>
<input type="checkbox">黴黴</input_type>
<input type="checkbox">李健</input_type>
<br>
性别:
<input type="radio" name="sex" >男
<input type="radio" name="sex" >女
<input type="radio" name="sex" checked>未知
<br>
上傳檔案:
<input type="file">
<br>
<input type="button" value="hello html" disabled>
<button>點我就有驚喜</button>
<br>
<!--連結--->
<a href="http://map.baidu.com">地圖</a>
<br>
<img src="//www.baidu.com/img/bd_logo1.png" height="129" width="270">
<br>
年齡:<select>
<option>20歲以下</option>
<option>20-25歲</option>
<option>25-30歲</option>
<option>30歲以上</option>
</select>
<br>
<form>
<input type="text">
<table border="2">
<tr>
<td>11<td>
<td>22</td>
<td>33</td>
</tr>
<tr>
<td>11<td>
<td>22</td>
<td>33</td>
</tr>
<tr>
<td>11<td>
<td>22</td>
<td>33</td>
</tr>
<tr>
<td>11<td>
<td>22</td>
<td>33</td>
</tr>
</table>
</form>
<iframe src="http://www.baidu.com">
</iframe>
<textarea></textarea>
<h1 id="title">大家好!!!</h1>
<h2>大家好!!!</h2>
<h3>大家好!!!</h3>
<h4>大家好!!!</h4>
<h5>大家好!!!</h5>
<h6>大家好!!!</h6>
<script >
//function aaa(){
// var a=[1,2,3,4,555];
// alert(a[1]);
//}
//aaa()
// window.οnlοad=function(){
// alert("everything is ready")
// };
#選擇console中這段代碼,滑鼠從左往右選中變藍色後,複制過來
a=document.getElementById("title");
a.onmouseover=function(){
a.style.color="red";
};
a.onmouseout=function(){
a.style.color="green";
};
</script>
</body>
</html>
Web頁面-簡單元素定位和定位輔助工具
學習目的:DOM對象+webdriver背後運作的原理。
Web自動化是通過驅動程式模拟自己是頁面點點點。
1.如何打開一個浏覽器?
selenium裡面有很多東西,第一個就是webdriver,web自動化中主流用的東西,它可以支援非常多的語言。它有個錄制工具是selenium ide,短期内一周内有個效果可以用錄制,錄制是非常簡單的。但是正經做項目的時候,是從來不用selenium ide的。
自己設計自動化架構,自己寫webdriver相關的事情。調用它實作比較長遠的自動化架構。不需要花時間了解selenium ide,知道有這個錄制的東西就可以了。
selenium grid,如果有ie,火狐,谷歌三大浏覽器,想讓三大浏覽器同時執行我的代碼。在不同的機器上執行,做這種分布式的模式,可以用這種selenium grid。
selenium grid要做webdriver能做出來的基礎上再去做分布式執行才有意義。
2.webdriver是怎麼工作的?
環境安裝的時候,每個浏覽器都有自己的驅動,如果現在想啟動一個浏覽器,要在代碼中選擇對應的浏覽器子產品來啟動。
3.有ie,火狐,谷歌,怎麼啟動其中一個呢?
不但驅動實作了與浏覽器的一一對應,代碼層面也實作了與浏覽器的一一對應。浏覽器之間有些設定上的差異。
driver=webdriver.Chrome()
這段代碼是怎麼和驅動程式通信的呢?
有python,java,ruby,c#版本的webdriver。都是第三方庫,都需要和chrome driver驅動程式進行通信。是通過http進行通信。
selenium webdriver庫,chrome driver,誰是用戶端誰是服務端?
http通信是一個用戶端去連接配接一個服務端,向服務端發送各種請求,等待服務端的響應。作為服務端要随時準備好接收用戶端的請求。
4.看chrome driver的源碼解析:
selenium webdriver庫向chrome driver這個驅動程式去進行http請求,将chrome driver啟動起來。
chrome driver是服務端。 service代表chrome driver這個服務。
預設啟動的是個什麼都沒有的浏覽器,希望在啟動的時候帶一些資料,保持一些什麼樣的配置等等。可以配置options和chrome options這兩個選項。這兩個選項可以暫時不用考慮。
在參數準備好後,第一件事就是啟動服務端,根據端口号和Ip位址啟動chrome driver。保證服務端線上,才可以發送請求。
第二進行連接配接。
第三發送請求。
和伺服器連接配接之後,我讓你做什麼事,那麼就是我們間定義好的一套協定。
代碼和chrome driver之間通信的協定。
什麼樣的請求代表通路網址,什麼樣的請求代表點選操作,什麼樣的請求代表輸入操作。
這套标準通用于APP測試。
web自動化和selenium webdriver用的是http請求,http協定。
通路個網址,點選個元素,相當于都是在發送一條http請求。
就像做接口測試一樣,發送一個http請求,等待它給我的響應結果。然後對響應結果字段進行解析,成功就成功,沒成功就抛出異常。
5.浏覽器的操作:
擷取浏覽器的屬性:
視窗,網頁位址,視窗的id。
能操作視窗之後,就把目标瞄準頁面。
1.元素查找。2.元素操作。
webdriver隻能操作網頁。windows浏覽器自帶的設定,webdriver是不能直接去操作這些東西的,這屬于一個視窗控件,不是html頁面。
webdriver隻能操作html頁面,超出範圍不行!
ChromeOption可以用變相的方式加載windows浏覽器自帶的這些資料,但是在頁面上不能看到操作效果。
6.代碼如下:
from selenium import webdriver
#将它執行個體化之後得到一個執行個體化對象,運作代碼打開谷歌浏覽器
# driver=webdriver.Chrome()
'''
此處有個坑:
python+selenium自動化測試~打開浏覽器報TypeError: 'module' object is not callable
原因是Chrome的首字母沒有大寫,寫成了chrome
'''
#打開的谷歌浏覽器是一個全新的浏覽器,沒有任何的使用者資料,就像網站中第一次下載下傳下來安裝後,第一次使用是一樣的。
#啟動谷歌浏覽器,開啟與浏覽器之間的會話。
driver=webdriver.Chrome(service_log_path="D://chromedriver_service.log")
#通路網頁
driver.get("http://www.baidu.com")#寫全網址的路徑。
#windows10裡面沒有chromedriver程序,windows7可能會看到好幾個chromedriver程序,這樣會導緻串門,
# 界面卡住不動
#視窗最大化
driver.maximize_window()
#通路
driver.get("http://www.taobao.com")
#回退上一頁
driver.back()
#回到下一頁(前進的意思)
driver.forward()
#重新整理
driver.refresh()
#屬性
#擷取标題
print(driver.title)
'''
如果是頁面點選打開,它會自動打開,但是想額外再打開一個,就要用js去執行。
'''
#擷取網址
print(driver.current_url)
#視窗的句柄(就是視窗的id)
print(driver.current_window_handle)
#關閉目前的視窗,沒有殺程序也沒有退出浏覽器程序。
# driver.close()
#代碼執行完畢後,殺程序,清理一些配置資料,徹底結束會話。
# driver.quit()
複雜元素定位
元素定位的各種方式
html頁面中的元素允許設定多個class的。樣式疊加起來的時候,可以設定多個class值。
如果想用
find_elements_by_class_name()
或者
find_element_by_class_name()
的時候,隻能選三個其中的一個class值,否則會報錯。
elements中的對象是所有符合這個條件的元素。web element對象,根據下标選擇對應的值去操作就好了。
1.與DOM對象對應的四種方式:
#方式一
ele=driver.find_element_by_id("kw")
# find_element_by_id傳回的是個web element對象。
print(ele)
print(ele.get_attribute("class"))
# 方式二 class
eles=driver.find_elements_by_class_name("s_ipt")
driver.find_element_by_class_name()#在html頁面,從上往下,找到第一個符合class值的元素。
#方式三 name
driver.find_element_by_class_name("wd")
driver.find_elements_by_name("wd")
#方式四 tagname
driver.find_element_by_tag_name("input")
driver.find_elements_by_tag_name("input")
其實也有
find_elements_by_id()
,但是id隻有一個,是以基本上不用這個。
針對連結這樣的元素,前面四種都适用,selenium webdriver額外多提供了兩種。
driver.find_element_by_link_text("更多産品")
不一定我找的連結隻有一個,可能有多個一樣的連結,是以這樣的方式一樣可以找到多個元素。
driver.find_element_by_partial_link_text("産品")
#部分比對
2.怎麼确定在這個html頁面中有這樣一個name屬性,class屬性,标簽名,其它元素都沒有呢?
需要掌握xpath表達式或者css表達式。
以上六種方式,僅僅針對某一個屬性。
有些情況下,光靠屬性,根本就找不到它。因為開發人員開發出來的都不一樣。
xpath和css是萬能定位方式,支援多種定位方式的組合。
不一定隻通過标簽名,可多種條件組合篩選。
項目做自動化的時候,盡量做到唯一定位,而不是在一堆元素中選一個。
xpath和css讓各種使用進行唯一定位的。
3.xpath表達式分為兩種。
相對定位
絕對定位:以/開頭,非常依賴頁面的順序和位置。父/子
絕對路徑:從頂層目錄開始,一層一層,所有經曆的層級全部都要列出來。絕對定位也是一樣的。
1代表第一個元素。
是從1開始的。
如果滑鼠放上去了,頁面沒有任何地方與它對應,可能這個元素是隐藏的,沒有顯示出來,也許是不是我要的元素。
右鍵拷貝path,是絕對定位,隻要稍微改動下,馬上就不行了。如果開發人員添加了元素,那麼馬上就會失效了。
系統也不是一層不變的,測試人員在上面測試,會新增修改删除資料,删除新增會導緻頁面結構發生變化。
如果項目比較大,元素定位比較多,有好幾百個的時候,就要哭了。
寫自動化用例要的是長期的效果,需要回歸用例的,這個東西需要運作半年以上,一年,兩年,三年的。正常做項目裡面不會用絕對定位。
都會采用相對定位。
架構是可以永久應用的,但是元素定位這個東西是和測試和系統相關的。是以想辦法改的越少越好。
4.相對定位為什麼比絕對定位好用呢?
相對定位中也是有個參照物的。相對于某個路徑,對于整個html頁面而言,它的相對定位就是相對根目錄。
相對定位:以//開頭不依賴頁面的順序和位置。隻看整個頁面中有沒有符合表達式的元素。
不管是誰的後代,不管是爺爺還是爺爺的爺爺,隻看整個html頁面有沒有。
既然沒有順序也沒有位置,隻要頁面沒有太大的變化,都可以定位到,而且不需要長期改。
寫xpath表達式,要檢測表達式到底能不能定位到元素。希望它實時檢測我的表達式能否真的定位到這個元素。
在Elements工具中,大家可以用一個底部彈出這個東西:
輔助我元素定位的。
5.要檢測相對定位怎麼做呢?
相對定位是//開頭,這是标準,這是文法分隔。
以//開頭,第一件事是要找下有沒有這個元素。
//後面首先跟的就是元素的标簽名也就是元素類型。
先把範圍鎖定起來,所有的屬性依賴于元素本身。首先确定下,這個類型的元素,頁面到底有幾個。
find Element by xpath 預設找到的就是第一個元素。
例如:
1 of 37表示一共有37個,目前是第一個。
要的不是目前第一個這種感覺,要的是完全絕對定位。
6.想絕對定位到它,一共隻找到一個元素怎麼辦?
通過類型篩選已經不能夠唯一鎖定它,在這37個input當中再通過一些其它的特征,再将這個範圍縮小到一個。
如果屬性是變動的就不要選,選不變動的屬性。
注意:屬性值要拷貝,不要自己輸入。有的時候看着沒有差別,但是就是有差別的。這樣一放,元素定位不到,就有點悲劇了。
提示1 of 1
這樣比絕對定位方式簡單太多了。
這是最最基本的一種相對定位表達式。
這樣比右鍵拷貝的好太多了。開發要是想新增元素,沒關系的,隻要我這個元素本身沒有變,其它的頁面愛怎麼變怎麼變,沒關系。它比絕對定位方式穩定性高很多,這個維護的成本會降低很多。
但是不代表相對定位就永遠都不要改,如果頁面發生了大的變化,那麼還是需要改的。
7.假設這個地方的name屬性不能唯一定位到它,input中有兩個元素的屬性都叫做userName,那該怎麼辦?
邏輯運算符:and or
想組合下條件,兩個屬性值都必須滿足。
根據實際需要,可以繼續and。
套路:先看有沒有,再看下有多少個,萬一有多的,就通過元素本身的屬性一步一步的縮小範圍。
定位的時候是會有元素出來,但是首先确定是不是我要找的元素。如果不是,那就再換。
在一個html頁面中,如果兩個元素一模一樣,通過自己的本身沒辦法定位到自己,就可以想點别的方法。
通過自己的各種屬性都沒有辦法確定我是絕對唯一的,那麼就這樣,如果在一個家族中某一個兄弟姐妹非常優秀,或者上級(爸爸或者爺爺)某一代中非常的優秀。
首先把範圍縮小到爸爸那輩或者爺爺那輩,在爺爺的子孫後代中找你就很簡單了。
元素定位是逐漸縮小範圍的。
比如選擇一個标簽名是首先縮小元素的類型,再去通過屬性再去縮小一個範圍。
層級定位,通過優秀的上級上上級來找到。雖然兩個元素是一模一樣,但是它們的父輩不一樣,可以現根據爸爸來找。
找到一個元素,要在它的後代找,可能是直系後代,也有可能是子孫當中。
在xpath表達式中什麼代表直系後代,什麼代表可以在子孫當中找,用/表達,/前後是父子關系。
雖然兒子輩有兄弟姐妹10個,每個人都有個name,但是它們的name都不一樣。
8.為什麼//也行?
這個元素的相對參照物是它爸啊。也就是
//div[@id="u1"]
是頂層節點,以它為基準。
以//開頭,後面的範圍逐漸縮小的時候,用//或者/都是可以的。
9.代碼如下
#元素定位
#id、 classname、tagname(标簽名)、
from selenium import webdriver
#啟動谷歌浏覽器,開啟與浏覽器之間的會話。
driver=webdriver.Chrome(service_log_path="D://chromedriver_service.log")
#通路網頁
driver.get("http://www.baidu.com")#寫全網址的路徑。
#方式一
ele=driver.find_element_by_id("kw")
# find_element_by_id傳回的是個web element對象。
print(ele)
print(ele.get_attribute("class"))
# 方式二 class
eles=driver.find_elements_by_class_name("s_ipt")
driver.find_element_by_class_name()#在html頁面,從上往下,找到第一個符合class值的元素。
#方式三 name
driver.find_element_by_class_name("wd")
driver.find_elements_by_name("wd")
#方式四 tagname
driver.find_element_by_tag_name("input")
driver.find_elements_by_tag_name("input")
#方式五、六 針對連結
# 如果是圖檔的連結,第五第六種用不了。如果是純文字的連結,可以通過文本内容來比對。
# 通過文字比對有兩種,完全比對,部分比對。
driver.find_element_by_link_text("更多産品")#全部比對
driver.find_element_by_partial_link_text("産品")#部分比對
#xpath
driver.find_element_by_xpath("")
# 絕對定位 以/開頭,非常依賴頁面的順序和位置。父/子
#相對定位 以//開頭 不依賴頁面的順序和位置。隻看整個頁面中有沒有符合表達式的元素。
#//标簽名稱[@屬性名="屬性值"]
# 邏輯運算符 and or //标簽名稱[@屬性名="屬性值"空格and空格@屬性名="屬性值"]
# 層級定位,通過優秀的上級上上級來找到。
#text() 文本定位。
#contains(@屬性名稱/text(),全部文本内容或者部分文本内容) 包含
#css
web頁面-複雜元素定位
xpath相對定位方式,除了我們講的這幾個之外呢,光靠這幾個做個項目的話,其實還是有難度的。
因為現在的開發人員沒有後面要做自動化這種意識,也沒有在做的時候考慮後面做自動化要怎麼做。
在公司發現元素定位特别複雜的時候,可以找開發同僚吃個飯(請他吃個飯)好好聊下,讓他幫你加點什麼。幫你加個id,友善你做元素定位。如果一個系統中很多元素都有唯一的id的話,這樣做起來非常快。
實際上,目前在做很多系統的時候你會發現,光有這些定位方式沒有辦法定位到所有元素。開發也是很忙的,也不搭理你。
1.xpath元素定位方式有更多的選擇。還有些定位方式是通過函數的方式實作的:
text()
是通過文本内容來定位。
div可以換成*,*代表比對所有元素。
無論頁面是任何一個元素,隻要id="u1"就可以。
第一種方式:
用相對定位避免用下标作為位置,除非實在沒辦法,都不要用它。
第二種方式:
自己靠得住的時候就不用靠關系了。
在相對定位中,可以用各種,看個人習慣,沒有絕對的定位方式,沒有絕對唯一的一種方式,可以有多種,但是有一些更好。
第一種方式更好,找id更快更準确一些,更穩定更快捷,不會因為時間的問題出啥幺蛾子。
有的時候光有
text()
定位也不能解決相關的問題。
contains
有兩個參數,可以是部分文本内容比對,也可以是部分屬性比對。
2.id的部分比對:
可變的id: 實際做項目的時候可能遇到這樣一個情況,一個元素的id由兩部分組成,id的值有一部分是固定的,後面是随機數或者别的東西變化的。那這個固定的是它的一個特征,跟你元素本身作用含義相關的。
這種情況下,能不能隻考慮id隻包含了前面固定的部分,如果能夠找到我就可以用它。
如果屬性中有部分是固定不變的,有特别意義的,那就可以用它。
3.通過部分class值來比對:
每個元素都有class,style這兩個屬性,一般可以看到一個元素有4-5個class值,style更長。style中有個屬性叫做visibility,代表它的可見性。
如果想通過style中部分樣式比對來找元素,用
contains
也是可以的。
像在字元串中查找内容,class值也是字元串,是以寫不全也是可以的。
但是一般的做法不會取class的一部分,會取某一個完整的class值。
有目前的這些方式也不一定夠用,有的時候定位不了一些特别複雜的元素,還有更多的用法。
4.軸定位:分析頁面中元素之間的關系。
當每一個元素的定位表達式都是一樣的,通過元素自己是定位不了,通過它的祖先定位也不行,祖先都一樣,那麼該怎麼辦呢?那就另辟門路。
我想通過我的兄弟姐妹或者後代或者先輩們來定位它,比如我和你之間沒有直接關系,但是我可以通過之間的關聯人來找到你。
這個是某種意義上的層級定位,隻不過這種定位很複雜。
就像搶頭标按鈕怎麼定位都是隻有3個,可以通過标的名稱找到搶頭标。把标的名稱作為一個變量。
5.軸定位包含這些東西:
百度上肯定不止這幾種,但是可以分析下,其它多餘的可以用别的方式來表達,沒有必要去整它的複雜模式。
标紅是使用率比較高的,未來使用比較靠譜的。
前面英文名字是它的軸名稱,後面是對它的關系的介紹。
preceding sibling:
目前元素節點标簽之前的所有兄弟結點。
html頁面中有同一個父親的子級都叫做親生兄弟姐妹。兄弟姐妹之間分先後順序也就是html頁面中的先後順序。
following sibling:
目前元素節點标簽之後的所有兄弟結點。
following:
是沒有兄弟姐妹關系的,也沒有所謂的家族關系。隻要在我後面出現的,都算是我後面的,無論是誰家的孩子。
preceding:
隻要你比我先出生,無論你是誰家的,那都是在我前面的。
following
和
preceding
其實是沒有太大意義的,是以也不怎麼用。
使用軸定位必須使用/後面再加軸定位,這樣定位更加精準,不能使用//,使用//會擴大範圍。
/軸名稱::節點名稱
6.什麼是軸名稱?
就是preceding sibling,ancestor,parent等這些。
7.什麼是節點名稱?
假如爸爸是div,爺爺是a,爺爺的爺爺是from,沒有說爸爸爺爺和爺爺的爺爺都是同一個元素同一個類型。都是随機的。
如果自己是個div,我的兄弟姐妹不一定就是div,有可能是a,也有可能是img等。
8.加節點名稱,友善在祖先兄弟姐妹中選一個符合你要求,比如我的兄弟姐妹中有兩個div,怎麼知道是哪個呢?
所有的定位方式全部都可以在[]裡面用,用前面的套路可以進一步的限定範圍。
首先分析python10專用和搶投标之間的關系。
隻能通過标名來定位它,标名根據用例的名稱來傳遞。
如果它們有個祖先是兄弟關系,可通過這一層來關聯。
方式一:
根據兄弟的後代有沒有a,決定選哪個。這種情況下就是使用軸運算的方式。
文本當然是會變得,可以将它作為變量。可以在元素定位中設定一個變量,沒有問題的。
實際做項目得時候,不會通過标名來選。這裡隻是個例子,沒有路可選得時候,可以選這條路。
實際工作中,元素定位可能比這個還要長,更加複雜,主要是根據系統來決定。
但是這種套路下,需要分析頁面布局和它們之間得關系。自己寫元素定位得時候,需要開動腦筋,想想哪種方式是最好的。
以上元素定位方式能夠定位到99%。
有些情況下比較特殊,不穩定的情況下用js,js是妥妥的最穩定的方式。js可以幫助你做元素定位,元素操作。
例如定位表格類型的資料,在某一個清單展示結果當中,表格中的列名是固定的。如果要定位某一行的資料,要擷取某一行某一列的元素,那隻能通過列名關系找到它對應的位置的值。這個在表格定位中應用的比較廣泛,其它場景用的不多。
表格用的上是因為表格有一樣的呀。
這些是xpath所有定位方式,絕對定位,相對定位,以及這些條件全部組合起來用,基本上可以解決99%以上元素定位。
實在不行還可以找到一系列元素再選下标。
這個系統設計的時候規定了首頁顯示的時候隻顯示3個标。 如果隻要第二個搶頭标按鈕。
方式二:
找到符合條件的三個元素,然後通過它的傳回清單當中,選第二個值,點選
find_elements()
也是按照先後順序往裡面放的,先找到的元素是第一個,後找到的元素是第二個,再找到的元素是第三個,一直往後放,它也是根據頁面順序來查找的。 是以,通過find_elements()找到元素後,通過下标去選就行了。
第三種定位方式:
根據某一個條件定位另外一個元素,就用到軸定位,例如看名字對應的學号。 表格性質的全部都可以用到軸定位。
/是絕對定位的一種,少用/,實在沒有選擇的情況下用下标。
元素操作
不會單獨介紹selenium webdriver的api,跟它的應用場景組合起來。
第一個,等待操作。
無論将來做app測試還是web自動化測試,必不可少的一部分叫做等待。
在web自動化中的三個切換操作。
第一,為什麼web自動化當中要做等待?
因為代碼執行的速度是非常快的,發送指令出去後,selenium chromedriver給我們回複消息的過程中,也許頁面渲染還沒有成功,渲染是需要時間的。
你要操作元素,它可能還沒有出現,于是會遇到很多初學者都會遇到的問題“noSuchElement",這個問題引起的原因比較多,第一點就是沒有等待元素出現,當然不僅僅是這個原因,很有可能是定位表達式在運作的過程中和你之前定位的時候是不一樣的,元素有了變化。
是以第一是元素定位的問題,第二就是等待的問題,第三個就是切換的問題,它是在另外一個html頁面中。
基于各種各樣的原因,必須要用到等待,web自動化中有3種等待方式,這3種等待方式,app通用。
1.強制等待。 不常用。
用來輔助第二種和第三種方式。
凡是你的操作引起了頁面的變化,你再要去操作的時候就一定要等待。
2.隐性等待。 不常用。
适用條件是查找元素和等待指令的執行完成。
如果機關是30秒,不會傻等30秒,如果你在30秒内找到了一個元素,比如第15秒找到了,那麼後面15秒就不再等了,在找到的時候就馬上去執行下一步,是以是種智能等待方式。
隻要在這個時間上限之内,這個元素出現了,什麼時候出現就什麼時候不再等待。如果超過30秒還沒有出現,就會抛出異常“TimeoutExceiption”,提示等待逾時了,元素至今還沒有出現。但是它是整個會話周期有效的。
3.什麼是整個會話周期?是什麼和什麼的會話?
打開浏覽器到關閉浏覽器。
這個期間隻需要調用
driver.implicitly_wait(30)
執行一次,在後續的過程中所有調用
driver.findElement()
,都适用于這條原則用來等待元素出現。
預設情況下是不等待的,如果在執行這個代碼的時候發現這個元素根本沒有出現,它不會立馬報錯,它會主動調用
driver.implicitly_wait(30)
這個隐性等待,在30秒之内隻要出現了都是可以的,30秒之内都不會給你報錯,不需要你刻意去調用,隻需要在會話中設定一次就夠了,可在會話啟動開始就設定下。
全局等待:
但是這個等待是有限定場景的。例如切換視窗的時候能不能等待新的視窗的出現,處理alert彈框的時候,能不能等待alert彈框的出現。
這種智能等待方式并不能解決所有的問題,有的情況下是不生效的。
4.必須掌握"顯性等待"
明确提出到底要等什麼,這個就叫做顯性,非常明顯的條件。
明确等到某個條件滿足後,再去執行下一步。
第一部分是等待,第二部分是條件。
等待:
由兩個東西來完成,第一個是WebDriverWait類,它是個顯性等待類,這個類中處理的事有什麼呢?
WebDriverWait類初始化的條件:
driver: 第一個是會話對象,就是說它要知道在哪個會話基礎上去等待什麼樣的條件完成,知道是在哪個頁面。
等待時長: 也就是最多等多少秒,例如等20秒,20秒以内,啥時候出現都不成問題。
輪循周期: 是多久去看一次,比如輪循周期是1秒鐘,就是每一秒去看下這個條件是否成立。
如果它每隔多少秒去看了下,最終在你等待的時限之内,還沒有找到一樣的,會報TimeoutException。
條件:
until是直到某某某條件成立,條件寫在()裡面的。
直到什麼條件成立,等到這個條件成立,
until_not()
就是等到這個條件不成立,直到找不到某個元素為止,直到頁面沒有哪個元素。
條件由誰來表達?
expected_conditions是一個子產品檔案,在它的子產品裡面有很多個類。這些類,一個類就是一個條件,有非常多的方法。
最最常用的是元素存在和元素可見。
5.使用之前引入相關的庫
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
web自動化有8種定位方式在By這個類中,詳情可以看源碼。
6.使用方法
先确定元素的定位表達式。
也就是你希望在什麼情況下等待。
一般是什麼情況下等待的呢?
比如找元素的時候,等待它出現,保險手段是寫個等待,如果不寫等待,也不一定真的不出現,隻是機率性的問題。
自動化代碼運作3遍可能沒有問題,但是運作5遍呢,其中有1遍是報錯的,告訴你元素找不到,是以每次在使用元素之前,去等一等,這是個非常穩定和保守的用法。
不需要每一步都去等,什麼情況下等呢?
點選操作導緻頁面發生變化,想在新出來的元素上面去操作,需要等到這個元素出現。
因為不知道頁面會給我響應多久,不知道等多久才可以看到這個元素,然後去操作它,是以要等到這個元素出現。
設定時長:智能等待,設定等待時間不要太苛刻,比如被測系統,平時測試的時候應該是5秒左右基本上所有頁面都能響應,但是做自動化測試最重要是追求腳本運作的穩定性,可以适當延長到7秒8秒,不要剛好卡在這個線上,有可能出現7秒8秒的現象。
輪循周期:WebDriverWait源碼中解釋了有個預設值,預設值是0.5秒。每0.5秒看下條件是否成立,是以使用預設值,第三個參數可以不用設定了。
條件是等到這個元素出現,直到條件成立為止。
建議安裝selenium webdriver的時候提供的-u方法,用-u将新的代碼更新進來了。
光看
TANGRAM__PSP_10__footerULoginBtn
,你不知道它是
id,classname
,還是
name
還是其它的什麼東西。
光看
TANGRAM__PSP_10__footerULoginBtn
,你不知道它是什麼類型的,是以在傳參的時候一定是定位類型和定位表達式都傳進來。
如果要定位類型和定位表達式兩個資料,它隻有一個參數,就用元組來表達,用這個類的時候就必須傳一個元組性質的參數進來,執行個體化的同時傳進來,
(元素的定位類型,元素的定位表達式)
執行個體化就是
EC.visibility_of_element_located()
定位類型就在By裡面選就可以了。
7.代碼
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
#web自動化有8種定位方式在By這個類中,詳情可以看源碼。
#啟動谷歌浏覽器,開啟與浏覽器之間的會話。
driver=webdriver.Chrome(service_log_path="D://chromedriver_service.log")
# 全局等待--隐性等待
# driver.implicitly_wait(30)
#通路網頁
driver.get("http://www.baidu.com")#寫全網址的路徑。
driver.find_element_by_xpath('//*[@id="u1"]//a[@name="tj_login"]').click()
# 這種情況下需要等待新的彈框出現,然後點選其中的使用者名密碼方式。
id="TANGRAM__PSP_10__footerULoginBtn"
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,id)))
#點選 使用者名密碼方式。
# driver.find_element_by_id("TANGRAM__PSP_10__footerULoginBtn").click()
是以它是由兩部分組成的,一部分表達條件,一部分表達等待。
EC.presence_of_element_located
頁面存在這個元素:能找到這個元素就可以了,不需要可見,是否隐藏都無所謂,隻要能找到就可以了。
隻要在html頁面中寫出來的,都可以找到。
這3種方式并不沖突,可以3種同時用,也可以選擇其中一種用,還可以選擇3種中的兩種,看情況用。
一般做項目用顯性等待是最多的,但是有的時候頁面千奇百怪,用顯性等待明明通過了,但是你想做更多操作的時候,它會提示這個元素找不到。
這種情況下,你會感覺很懵,明明等待了,為什麼說找不到呢?
如果遇到這種非常奇怪的現象,去組合下sleep(秒),sleep(秒)在自動化代碼中使用頻率不是太低。但是主要目的是協助顯性等待,盡量提高運作的穩定性。
sleep(秒)的時間一般也就1秒2秒左右,不會是5秒7秒,這種用法是很浪費時間的。在顯性等待後,用sleep1秒或者0.5秒,0.2秒,或者2秒來輔助一下就可以了。sleep(秒)僅僅是個輔助功能。
寫多了sleep會影響效率嘛?
不會。
sleep()
不要等太長時間,0.5秒,1秒,2秒鐘影響不大。需要的地方才用。
在你沒法處理的時候用sleep(),能處理的時候就不用
sleep()
,如果頁面中太多了,當然還是會影響執行速度的。
更多軟體測試資源分享微信公衆号:【程式員阿沐】
軟體測試技術交流群:
一個用心碼了這麼多文字的人,往往渴望得到大家的認可。如果你覺得這篇回答對你有幫助,輕按兩下螢幕,給我點個贊呀!