1. 程式人生 > >selenium webdriver 頁面css和xpath定位

selenium webdriver 頁面css和xpath定位

對於html來說,不管用什麼瀏覽器開啟,他的架構是不變的,所以對於編寫自動化測試程式來說,基於什麼瀏覽器開發,差異不大,所以這裡推薦使用chrome 65或以後版本瀏覽器,之所以推薦這個瀏覽器,是因為它可以不用安裝任何外掛,就可以很方便的提供定位相關的功能。

chrome瀏覽器可以用F12調出除錯視窗,用ctrl + F可以調出選擇器和xpath搜尋輸入框,在搜尋時可以顯示搜尋到結果的個數,如果搜尋的結果個數比較多,說明對應的選擇器或者xpath有問題,因為結果不唯一,除非希望儲存的結果是一個集合。

一、CSS選擇器定位

1.使用標籤名查詢元素

這個比較簡單,但是基本上不會用。也就是說如果一個頁面中該型別的標籤只有一個,那麼只要定位該標籤就好了。比如一個頁面中只有一個input標籤,那麼只要將這個個input用於定位就行了

2. 使用ID選擇器查詢元素

缺點:

a. 如果頁面的ID不是惟一的,或者會動態變化,不太適合使用這個選擇器

b. 如果ID是惟一的,但是對應元素的其他屬性是變化的,比如name,text等會變化,也不太適合使用多條件判斷

需要注意的是,在元素定位過程中,如果定位的元素不是惟一的,都是會出錯的,除非查詢的是多個元素組成的list

語法:  tag[attribute='value']

tag就是html中的標籤,可以是input,p, a等等

attribute標識屬性,對應css選擇器來說,它的屬性是id或者class

value就是屬性的值,一般用單引號包含

  <div id="bdSug_1521883224738" class="bdSug_wpr" style="display: none;"></div>

比如需要定位這一行,可以使用:

#bdSug_1521883224738

div[id='bdSug_1521883224738']

div#bdSug_1521883224738

一般來說,一個DOM的ID都是惟一的,但是如果多個不同的標籤使用了相同的ID,那麼可以在定位的時候也指定標籤,以保持定位惟一,這裡需要注意的是,雖然在匹配id的時候可以不用完全匹配,但是在寫程式碼的時候儘量完整

3. 使用類選擇器查詢元素

ID用點標識,class用#標識

(1)完全匹配

<div id="myCarousel" class="slide" data-ride="carousel">

#myCarousel 或 div[id='myCarousel'] 或 div#myCarousel

.slide 或 div[class='slide'] 或 div.slide

<div class="carousel-item csdn-tracking-statistics" data-mod="popu_465" data-dsm="post">

div[class='carousel-item csdn-tracking-statistics']

這裡需要注意的是,class這種寫法並不支援部分匹配,如果上式寫成div[class='carousel-item']將會定位失敗,即使少個尾部空格也不行。

這種寫法要求寫出標籤中的所有class完整值

(2)部分匹配

那如果一個位置上包含多個class屬性的時候應該怎麼定位呢?可以使用追加屬性的方法。

.carousel-item.csdn-tracking-statistics

這表示滿足第一個class的同時滿足第二個class屬性的值。如果這還不能惟一定位,那就只好找相對定位的方法了

這種寫法要求寫出標籤中的部分class完整值

(3)通配

上面兩種匹配方式都要求使用者在匹配class的時候使用完整的class屬性值,但是通配可以做到更靈活的匹配

^表示文字開頭

$表示文字結尾

*表示任意文字

語法: tag[attribute<wildcard>='value']   其中wildcard表示萬用字元

<div class="carousel-inner" role="listbox">
<div class="carousel-item csdn-tracking-statistics" data-mod="popu_465" data-dsm="post">
<div class="carousel-item  carousel-inner csdn-tracking-statistics" data-mod="popu_465" data-dsm="post">

如果要匹配這三行可以用  div[class^='carousel']

如果要匹配後面兩行用 div[class$='statistics']

如果要匹配其中包含inner的行,用 div[class*='inner']

上面介紹了使用id和class進行定位,其實這並不是最厲害的,厲害的是這兩個屬性的定位方法可以拓展到其他屬性上,比如:

<link rel="alternate" media="only screen and (max-width: 640px)" href="https://m.imooc.com/">

可以使用 link[rel^='alt'] 進行定位

<meta name="mobile-agent" content="format=xhtml" ;="" url="https://m.imooc.com/">

使用 mata[name$='agent'] 定位

<a href="/" target="_self" title="首頁"><img title="慕課網" src="/static/img/index/logo.png"></a>

使用 a[title='首頁'] 定位

裡面的img使用 img[title='慕課網'] 定位

4. 用CSS定位子節點

father>son[attribute='value']>grandson[attribute='value']

		<div class="carousel-item csdn-tracking-statistics  next left" data-mod="popu_465" data-dsm="post">
			<a href="http://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/79643977" target="_blank">
				<img src="//csdnimg.cn/feed/20180321/6c98086f1d03ee4f653afaab114f163e.jpg">
			</a>
			<a href="http://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/79643977" target="_blank">
				<div class="carousel-caption">
					機器學習大神邁克爾 · 喬丹:我討厭將機器學習稱為AI				</div>
			</a>
			<a href="http://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/79643977" target="_blank" style="display:block;">
				<div class="cover"></div>
			</a>
		</div>

定位子節點也可以叫相對定位,也就是說在用CSS定位時,有些元素不能通過一次性直接完成定位,需要通過定位其惟一的父節點,然後再相對定位到子節點上。其中比較常見的有table,list以及一些並列的元素。

比如對於上面這些<a>標籤是並列的,如果要定位第二個<a>標籤可以用 div > a > .carousel-caption

二、XPATH定位

一般來說上面的定位方法不夠用的時候,就會拿出終極武器xpath進行定位了,因為xpath定位並不需要它的屬性是惟一的,或者是固定不變的,不管在哪裡,它總能找到它。

1. 基本語法

語法: //tag[@attribute='vale']  有沒有發現,xpath定位的時候,屬性的前面多一個@

xpath的語法就不介紹了,可以網上查查,這裡主要說明幾個:

/ 表示父節點的下一個節點

// 表示父節點的下面某個節點

* 用於通配標籤名,切記不要用來通配節點路徑

div > p > li > a > span

         p > li

         h > a

比如有這樣一個html層級巢狀結構,div下面有三個p標籤, 如果父節點是 div,那麼 div/ 後面接的只能是 p或者h標籤, div// 後面接的可以是除div意外的任意一個標籤。以下這些寫法是對的:

//div/p/li

//div/h/a

//div//li//span

這種寫法是錯的: //div/a   //div/p/span

2. 用text和contains構建xpath

語法: 完全匹配  //tag[text()='value']

           部分匹配 //tag[contains(attribute, 'value')]

<ul class="nav-item">
            <li class="set-btn visible-xs-block js-header-avator"><a href="/u/1372187" target="_self"><img width="40" height="40" src="//img4.mukewang.com/5333a2320001acdd02000200-100-100.jpg"></a></li>
                        
            <li>
                <a href="/course/list" target="_self">免費課程</a>
            </li>           
            <li><a href="//class.imooc.com" class="program-nav " target="_self">職業路徑<i class="icn-new"></i></a></li>
            <li>
                <a href="//coding.imooc.com" target="_self">實戰</a>
            </li>
            <li><a href="/wenda" target="_self">猿問</a></li>
            <li><a href="/article" target="_self">發現</a></li>
            <li class="visible-xs-block"><a href="/user/setprofile" target="_self">我的設定</a></li>
            <li class="visible-xs-block"><a href="/passport/user/logout?referer=//www.imooc.com" target="_self">退出</a></li>
</ul>

比如要定位text為“發現”這個標籤,可以用 //ul//a[text()='發現'] 進行定位, 但是text的內容必須完整的寫過來

當然也可以使用部分匹配: //a[contains(text(), '免費')]   用於匹配在a標籤種text帶有‘免費’的位置

也可以判斷其他屬性的值是否包含關鍵字:

//a[contains(@class, 'program')]    //a[contains(@href, 'article')]

不僅如此,它還支援多條件合併:

<a href="/wenda/detail/383123" target="_blank" class="wenda-tit">【有獎問答】與大咖交流前端JS與框架開發,免費贏取前端圖書(11.28-12.4)</a>
它可以用多個條件進行定位: //a[contains(@href, 'detail') and contains(@class, 'tit') and contains(text(), '大咖')]

3. 用starts-with構建xpath

語法: //tag[starts-with(attribute, 'value')]   查詢屬性值以value開頭的位置

<a href="/wenda/detail/383123" target="_blank" class="wenda-tit">【有獎問答】與大咖交流前端JS與框架開發,免費贏取前端圖書(11.28-12.4)</a>

//a[starts-with(text(), '【有獎問答】')]

//a[starts-with(@class, 'wenda')]

//a[starts-with(@href, '/wenda')]

4. 查詢父節點、前面平級節點、後面平級節點

父節點 = //parent::<tag> 

前面平級節點 = //preceding-sibling::<tag>   

後面平級節點 = //following-sibling::<tag>

<ul class="nav-item">
            <li class="set-btn visible-xs-block js-header-avator"><a href="/u/1372187" target="_self"><img width="40" height="40" src="//img4.mukewang.com/5333a2320001acdd02000200-100-100.jpg"></a></li>
                        
            <li>
                <a href="/course/list" target="_self">免費課程</a>
            </li>           
            <li><a href="//class.imooc.com" class="program-nav " target="_self">職業路徑<i class="icn-new"></i></a></li>
            <li>
                <a href="//coding.imooc.com" target="_self">實戰</a>
            </li>
            <li><a href="/wenda" target="_self">猿問</a></li>
            <li><a href="/article" target="_self">發現</a></li>
            <li class="visible-xs-block"><a href="/user/setprofile" target="_self">我的設定</a></li>
            <li class="visible-xs-block"><a href="/passport/user/logout?referer=//www.imooc.com" target="_self">退出</a></li>
</ul>

父節點:

ul_xpath = "//a[text()= '職業路徑']//parent::li//parent::ul"

父節點應該會比較好理解,但是前平級節點和後平級節點可能會不好理解,它的意思就是,基於當前節點,往前的平級節點,或者往後的平級節點。

前面平級節點:

第一個和第二個<li>標籤  = "//a[text()= '職業路徑']//parent::li//preceding-sibling::li"

第一個<li>標籤 = "//a[text()= '職業路徑']//parent::li//preceding-sibling::li[1]"

第二個<li>標籤 = "//a[text()= '職業路徑']//parent::li//preceding-sibling::li[2]"

後面平級節點:

第一個和第二個<li>標籤  = "//a[text()= '職業路徑']//parent::li//following-sibling::li"

第四個<li>標籤 = "//a[text()= '職業路徑']//parent::li//following-sibling::li[1]"

第五個<li>標籤 = "//a[text()= '職業路徑']//parent::li//following-sibling::li[2]"


關於定位的,到這裡基本上就夠了,這裡總結一下吧,在定位的時候:

如果id是惟一的,用id定位最快;

如果name或其他屬性是惟一的,則用其他屬性;

如果上面不行,則用CSS的組合選擇器定位;

最終沒招了,用xpath吧!!

但是,這也不是絕對的,具體問題具體分析吧!在我看來,只要哪些定位方式受html變動影響比較小的,或者即使變了也不會影響定位的,這種定位方式是優先選擇的,對於自動化測試,並不要求程式碼能執行多快,應該多保證這些程式碼怎麼能夠提高通用性、拓展性以及專案間的可移植性。