<h3>一、Xpath定位方法深入探討</h3>
(1)常用的Xpath定位方法及其特點
<h6>使用絕對路徑定位元素。</h6>
例如:
driver.findElement(By.xpath("/html/body/div/form/input"))。
特點:這個路徑是從網頁起始標簽開始一直到要定位的元素的路徑,如果要定位的元素在頁面最下面,則這個Xpath路徑會非常長。如果在要定位的元素與頁面開始之間的元素有任何增減,元素定位就會失敗。
<h6>使用相對路徑定位元素。</h6>
例如:
driver. findElement(By.xpath ("http://input") )
返回查找到的第一個符合條件的元素。
特點:相對路徑一般只會包含與被定位元素最近的幾層元素有關,相對路徑寫的好的話,頁面變動影響最小,而且定位準確。
<h6>使用索引定位元素,索引的初始值為1,注意與數組等區分開。</h6>
例如:
driver. findElement(By.xpath ("http://input[2]") )
返回查找到的第二個符合條件的元素。
特點:如果一個頁面中有多個相似的元素,或是一個層下面有多個同樣的元素的時候,需要用索引的方法來定位,否則無法區分。
<h6> 結合屬性值來定位元素。</h6>
例如:
driver. findElement(By.xpath ("http://input[@id='username']"));
driver. findElement(By.xpath ("http://img[@alt='flowr']"));
特點:屬性定位也是比較常用的方法,如果元素中沒有常見的id,name,class等直接有方法可調用的屬性,也可以查找元素中是否有其他能唯一標識元素的屬性,如果有,就可以用此方法定位。
<h6> 使用邏輯運算符,結合屬性值定位元素,and與or。</h6>
例如:
driver.findElement(By.xpath("http://input[@id='username' and @name='userID']"));
特點:多個屬性值聯合定位,更能準確定位到元素。并且如果多個相同標簽的元素,如果其包含的屬性值有不同的,也可以用這個方法區分開來。
<h6>使用屬性名來定位元素。</h6>
例如:
driver. findElement(By.xpath ("http://input[@button]"))
特點:此方法可以區分同一種標簽,含有不同屬性名的元素。定位相對簡單一些兒,但也同樣存在著無法區分同種標簽含有同種屬性名的多個元素,這個時候要配合索引定位才行。
<h6> 類似于cssSlector,使用部分屬性值匹配元素.</h6>
例如:
(a)starts-with()
driver. findElement(By.xpath ("http://input[stars-with(@id,'user')]"))
(b)ends-with()
driver. findElement(By.xpath ("http://input[ends-with(@id,'name')]"))
(c)contains()
driver. findElement(By.xpath ("http://input[contains(@id,"ernam")]"))
特點:此方法更加靈活,可以定位屬性值不太規律,或是部分變動,中間有空格的情況。注:如果屬性值中間包含空格,Webdriver定位的時候容易出錯,時而能定位到時而定位不到,所以應該避免用含用空格的屬性值定位。可以采用此方法,進行部分屬性值定位。
<h6> 使用任意屬性值匹配元素。</h6>
例如:
driver. findElement(By.xpath ("http://input[@*='username']"))
特點:此方法相當于模糊查詢,只要欲定位的標簽,如input中任何屬性值等于‘username’,就能匹配成功。缺點,可能會匹配含有這個屬性值的其他元素,所以我們在定位的時候要查看一下這個元素值在頁面中是否唯一。
(2)運用Xpath定位元素的思路
當我們在做自動化測試的時候,欲對一個頁面元素定位,通過上面我們講到的選擇定位方法篩選后,決定用Xpath定位了,此時我們應該怎么寫Xpath呢?請按以下步驟來分析:
(a)先看一個這個元素是否有明顯的,唯一的屬性值。如果有,我們就用相對路徑加屬性值定位,這是最簡單準確的定位方法。如:
//input[@alog-alias=’search’]。
(b)如果要定位的元素,不符合上面的特癥,元素屬性要么是動態的,要么就是不能區分這個元素的,還有就是屬性值中間有空格的情況,都無法定位。所以從此元素開始,向他的上一層查找。
(c)當遇到了一個符合條件的元素時,對其寫Xpath,然后在Selenium IDE中驗證是否能定位到該元素。如:
//div[@type=’good’],
在Selenium IDE中驗證能定位到這個div。
(d)然后從這個元素開始,一級級往下寫,真到要定位的元素為止。如果你比較肯定寫的是正確的,可以寫完后再驗證,如果不肯定,就寫一層,用Selenium IDE驗證一下,以確保安全。如:
//div[@type=’good’]/div/input
(e)當Selenium IDE定位成功后,再放到測試用例中去調試運行。雖然Selenium IDE能定位到的代碼也能定位到,不過還有因為延遲,操作順序等會影響代碼定位的因素存在。
<h3>二、元素定位不到的原因及解決辦法</h3>
在我們編寫自動化測試用例的過程中,經常會遇到元素定位不到的現象,有的時候我們用Selenium IDE檢查的時候也能在Firebug中看到,可是運行代碼的時候,總是提示元素找不到。經過我以往和經驗和大家在網上的討論,我總結了以下幾種情況:
(1)定位屬性值是動態變化的情況
現象:在我們定位元素的時候,發現有id, name或其他的屬性存在,于是就用相應的定位方法去定位??墒沁\行的時候提示定位不到,然后我們再去查看元素的時候,發現屬性值和我們寫代碼的時候不一樣了。
原因:通常產生這種情況的原因就是你使用的屬性值是動態變化的,主要表現有屬性值是一串數據,或是字符加一串數據等情況。頁面加載一次變化一次,每次都不相同。
解決辦法:我們應盡量避免用這樣的屬性值去定位,而采用這個元素下的其他固定不變的屬性值。或是向上層查找,采用Xpath定位。
(2)Iframe中的元素定位出錯的情況
現象:我們在定位元素的時候,查看網頁源碼,發現有iframe存在。可是我們沒有做特殊處理,而是直接用通用的定位方法,name ,id, xpath或者CSS來定位。用Selenium IDE驗證能查找到元素,可是運行測試用例的時候,總是元素找不到。
原因:在我們運行測試腳本的時候,代碼獲取的是頁面的句柄,而iframe在句柄中是當成一個元素來處理的。腳本是沒有辦法自己去iframe中去定位元素的,所以當搜索完頁面時,發現找不到要定位的元素,就當錯誤處理。
解決辦法:當需要定位iframe中的元素的時候,先將句柄切換到iframe中
(driver.switchTo().frame("framename");)
然后再去定位,就能定位到要測試的元素。
(3)不同頁面或iframe切換時元素定位情況
現象:當我們在編寫測試用例的時候,會遇到打開一個新頁面,或是切換到一個新的iframe中,然后再去定位元素進行操作。但是我們的定位方法寫的沒有問題,而且在Selenium IDE中也驗證通過,可是代碼運行的時候還是會提示找不到元素。
原因:其實這個和定位iframe中元素的情況是一樣的,在打開一個頁面或是切換到一個iframe的時候,driver獲取的是當前頁面或是iframe的句柄。當你的操作切換到新的頁面或是iframe的時候,如果代碼不去做相應的切換,查找元素的時候還會在原來的句柄下查找,當然會出現查找不到的情況。
解決辦法:當操作切換頁面或是iframe的時候,我們的測試腳本也要做相應的切換,選擇新打開的頁面或是切換到新的iframe下。然后再去定位的時候,就會在新頁面或是iframe下定位了。
(4)Xpath編寫出錯的情況
現象:如果我們對一個元素編寫了對應的Xpath,然后在沒有通過Selenium IDE進行驗證的情況吧,就去編寫代碼執行測試用例。會出現查找不到元素的情況,或是頁面發生了變化,導致Xpath路徑有了變化,也會查找不到元素。
原因:主要的問題就是Xpath編寫出錯了,或是頁面有改動。不管是增加了新的模塊或是隱藏的div,都會影響Xpath路徑的。
解決辦法:將代碼中的Xpath拷出來,放到Selenium IDE中進行驗證。如果出錯了,就做相應的修改。這個也是代碼維護中當遇到的問題,被測試對象變化,導致測試用例的修改。
(5)操作速度過快,被定位的元素沒有加載出來的情況
現象:在測試用例運行過程中,會出現被定位的元素有的時候能定位的到,有的時候卻定位不到的現象。而我們去頁面上驗證我們的定位方法的時候,沒有一點兒問題,顯示不是定位方法寫錯了。
原因:這種情況多半是因為測試用例執行到代碼的時候,被定位元素沒有加載出來造成的。網速原因,執行代碼的機器原因,都會造成加載比程序執行的慢的情況。
解決辦法:在我們定位元素之前,評估一下頁面的加載情況,如果有加載慢的地方,需要添加一定等待時間
self.sleep(5000),
等上幾秒后再去定位操作。
(6)定位頁面嵌入式元素的情況
現象:在頁面中會有一些兒嵌入式元素,如object,播放器等。這個時候,我們對其操作的時候,是無法定位到上面的元素的。
原因:嵌入式元素對webdriver來說是一個元素,不管里面包含多少元素,都無法操作。對于object對象,網上有說要對相應的Flash重新編譯,添加相應的代碼或是控件才能定位。但這樣一樣又不安全了,所以嵌入式對象一直是自動化測試的盲區。
解決辦法:嵌入式對象如果是簡單的單擊操作,可是用模擬鼠標單擊相應的區域,就能完成操作。如果是輸入操作,我們可以先模擬點擊輸入區,然后模擬鍵盤進行輸入。除此之外,好像也沒有什么好的辦法。
(7)firefox安全性報錯的情況
現象:firefox安全性強,不允許跨域調用出現報錯,錯誤描述:
uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMNSHTMLDocument.execCommand]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location:
原因:這是因為firefox安全性強,不允許跨域調用。
解決辦法:Firefox 要取消XMLHttpRequest的跨域限制的話,
第一是從 about:config 里設置
signed.applets.codebase_principal_support = true; (地址欄輸入about:config
即可進行firefox設置)。
第二就是在open的代碼函數前加入類似如下的代碼:
try{
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
}
catch (e)
{
alert("Permission UniversalBrowserRead denied.");
}
對錯誤進行處理。
喜歡就留下你的贊吧