WebUI自動化測試過程中遇到的問題總結
hosts檔案修改為:
127.0.0.1 localhost
127.0.0.1 static.mediav.com
127.0.0.1 www.google-analytics.com
我一開始的程式碼:
報錯說元素是不可見的,然後將Xpath進行修改://input[@type='password'][1],執行成功了,但是下次再執行的時候又報錯了!現在開始仔細檢查Html程式碼,發現只有當用戶在密碼框中點選一下之後,儲存密碼的那個input才會變成可見的,不知道為什麼我剛剛那種錯誤的修改方式還執行成功了!!! 滑鼠在密碼框中點選一下之後,密碼這部分的Html程式碼:
再次修改程式碼如下:
再次執行,成功登入 3、 獲取市價 首先在瀏覽器中利用Xpath Checker獲取到儲存市價的那個文字框,Xpath如下:
然後在程式碼中獲取內容: 執行,市價為空 以為獲取方式有問題,換獲取方法,換xpath的書寫方式等等,怎麼操作怎麼是空,然後換了一個頁面,獲取其他文字框中內容,驗證我的獲取方式是沒有錯的,然後再次檢視html程式碼:
恍然大悟,發現這地方的值不是內容啊,是value屬性!! 終於找到問題,修改程式碼: 再次執行,市價成功! 4、點選登入
有一次利用xpath獲取”登入“按鈕後,點選,結果好像報錯說不能點選,還是跳不過去,最後發現是好像瀏覽器認為我的路徑部分是不能點選的,需要/..到父親級別才可以點選。
推薦一篇文章xpath使用技巧: http://www.ibm.com/developerworks/cn/xml/x-xpath5tips/
講的都是一些實用技巧。
5、第三方登入-iframe導致定位不到元素
最近在做UI自動化測試的時候遇到一個問題,網站支援第三方登入,如QQ,從網站進入到QQ登入頁面進行的很順利,進入之後的頁面如下:
我想點選的是“賬號密碼”登入,firebug顯示的這是一個a標籤,好,直接通過xpath定位,結果,找不到。。。
想了很久不知道什麼原因,問師傅,說“外面是不是有iframe”。
知道了原因就很好辦了,有iframe時需要先進入iframe,才能找到想要的元素,見識太少了啊!
具體解決方法:
//先進入iframe,找到元素再點選
WebDriver driver = be.getBrowserCore();
driver.switchTo().frame("ptlogin_iframe"); //字串為iframe的id
driver.findElement(By.id("switcher_plogin")).click();
Selenium定位不到元素的解決辦法-iframe擋住了去路 http://www.blogjava.net/qileilove/archive/2014/01/02/408358.html 謝謝分享
當處理完iframe相關操作後,在進行其他後續操作前,記得移出iframe:driver.switchTo().defaultContent();
6、第三方人人登入:
具體樣子是開啟網站首頁,點選登入,選擇人人登入,會新開一個頁面要求輸入人人賬號和密碼,輸入完成後點選登入會自動關閉本頁面兵跳轉到網站首頁,流程上寫完之後,執行,會看到整個流程都是按照預想的執行的,頁面上也可以看到賬戶已登入成功,但是我沒有做驗證,突然加了一個驗證語句,be.expectTextExistOrNot(true, "恭迎", 2000);(登入成功之後會有恭迎),但是這時候會報錯,錯誤:org.openqa.selenium.NoSuchWindowException: no such window: target window already closed,說頁面已經關閉,是啊,頁面是關閉了,但是我想找的元素是在當前頁面上啊。。。問題是,新開頁面之後我通過 be.selectWindow(WindowTitle); 選擇了新開的頁面,但是當新開的頁面關閉之後我並沒有在程式中返回原來的頁面,這樣子瀏覽器模擬器還是在新開的頁面上,所以它會說頁面已經關閉了,找不到元素了,解決方法,在新開的頁面關閉後返回到原來的頁面。但是不能再通過選擇Title的方式回去了。
這個例子介紹了可用的方法:
http://wenku.baidu.com/link?url=tRIfyv86Qv1LmT77kzXzs-Rg9X1ZyuMaIqlomXD4cqiHrsG0yHyQ885i3p6_E3n_XBw7TzioeWeYybXccpFe4bn1fcnB13kiPrj6K_pufcy
我的實現:
在頁面轉換到新頁面前先獲取當前視窗的控制代碼,
String currentWindow = be.getBrowserCore().getWindowHandle();
...............
處理完成後,再返回到原來的頁面
be.getBrowserCore().switchTo().window(currentWindow);
總結:自動化是電腦來實現的,程式碼是死的,你讓它幹嘛它就幹嘛,記住了,頁面轉換之後你不讓它轉回去它是不會自己回去的。
7、xpath 定位規律:
如果元素有id那就用id;
沒有id那麼可以看看class是不是唯一的;
再搞不定那就先找準一個祖先節點,然後往它的子孫找直到到達目標元素
//div[@class=' param f-cb '][1]//li[1]/a子孫,難以直接定位
8、一個輸入框,顯示數字,html的顯示如下:
沒有顯示數字,現在要獲取輸入框中的數字,普通的直接getText()是行不通的,方法:
這個輸入框的數字是通過input的value屬性來顯示的,所以需要獲取的是input的value屬性。
獲取值:be.getBrowser().getValue("//input[@class='mark-input']");
現在有一個需求是要修改數字,直接be.type會在1後邊新增,即如果輸入5,會變成15
用js執行,be.getJavaScriptExecutor().executeScript("return document.getElementsByClassName('mark-input').value=" + numString);不會改變(不確定程式碼是否對)
最終解決辦法:
WebElement webElement = be.getBrowserCore().findElementByXPath("//input[@class='mark-input']");
//先輸入退格鍵,清除原來的1
webElement.sendKeys(Keys.BACK_SPACE);
webElement.sendKeys(numString);
輸入新的數字前,先利用退格鍵刪除原來的1,然後再輸入。
總結:這幾天其實遇到的都是一些定位獲取元素及元素值的問題,看起來都是一些小問題,但是第一次遇到的時候會浪費很多時間,因為沒有經驗不知道如何下手,檢查很久也不一定能找到問題,個人感覺UI自動化受外界影響要多一點,需要多鍛鍊。
通過這幾天寫程式碼,也發現了自己的缺點:
1、需要多總結一些經驗;
2、前端知識不夠了解,像js之類的,有空需要好好學習一下;
3、對Selenium的API不熟悉。現在寫程式碼都是想要什麼的時候去查詢,並不知道Selenium到底提供了哪些方法,沒有從總體上掌握,這個需要加強。
9、一個異常 org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
意思就是Element已經過時,沒有和當前頁面進行繫結,主要是頁面重新整理或者跳轉引起的。需要重新獲取一次元素。
我的程式碼是按照步驟來操作的,可能是由於操作過快,前一個點選了但是頁面還沒來得及反應,下一個執行一半的時候頁面反應了,所以導致元素過期,這個只需要上一個操作完成後等待一下再執行下邊的即可。
10、UI自動化中的一個坑
購物車中有很多商品,每一個後邊對應一個刪除按鈕,現在要將購物車中的所有商品刪除,開始時的做法是首先獲取頁面上刪除按鈕的個數,然後迴圈點選每一個刪除,程式碼如下:
寫完後,往購物車中加了兩個商品,進行驗證,哇~一次通過!!
今天,寫測試用例的時候,購物車中的商品多了幾個,然後清空購物車,哦MyGod,刪除了兩個商品之後就報錯:
錯誤是元素不在頁面上了,之前出現過這個問題,是因為頁面重新整理或者跳轉導致了,那這地方就只能是頁面進行了重新整理,為什麼還成功的刪除了兩個那?因為自動執行速度很快,在頁面重新整理的中間過程成功的刪除了兩個,這也是為什麼我之前購物車中有兩個商品的時候會成功的原因!!
好大的陷阱,不知道我的程式碼中還有多少個地方是僥倖成功的啊。。。。。
既然每刪除一個商品之後頁面都會重新整理一次,那好了,每刪除一個商品再重新獲取一次吧:
11、第一個問題
- XPath 表示式
//Name[1]
選擇第一個<Name>
元素,無論它位於 XML 文件中的何處。因此係統中若有多個name元素處於第一個,則都返回 //Document[1]/Name
,這返回第一個<Document>
元素的<Name>
元素- (//Name)[1],該表示式選擇所有的
<Name>
元素,然後返回第一個元素
12、新開頁面
寫UI用例,遇到新開頁面的情況,需要將對頁面的定位在開啟的頁面上進行轉換,方法如下:
- be.selectWindow(WindowTitle);
- 直接使用be.open(url);開啟要去的頁面