整個iQuery的代碼是開源的,今后也將有后續文章講解iQuery的實現方式,對iQuery有興趣的朋友可以在此下載或者同步代碼:
https://github.com/vowei/iQuery
在程序界面(UI)自動化測試中,最煩人的就是抓取控件的過程了,要么是程序員忘記在代碼里給控件添加自動化測試用的標簽;要么就是界面布局經常變,如果是基於坐標位置抓取的話,一點小變化都很麻煩。碰到這種問題很討厭,界面變更導致的測試失敗由於跟產品問題無關,因此開發一方經常會拒絕修改代碼,問題全部丟給測試工程師一方。而在手機應用上,這種問題就更突出了,一個市場占有率較廣的應用通常都支持好幾個平台,而各個平台的編程方式還不一樣……
iQuery的思路借鑒自jQuery(或者說是CSS)的選擇器,一方面提供一個比較簡單的方式在自動化測試程序里抓取控件,一方面試圖通過將控件歸類提供一種跨平台統一的控件抓取表述語法。它是一個多平台通用的控件查詢語法,當前已經實現了iOS版,支持在Instrument里使用,本文介紹iQuery在iOS上Instrument中的用法。
我們盡量將iQuery的語法與jQuery的語法保持一致,然而由於二者的目標不一致(jQuery致力於盡可能多的抓取控件,而iQuery則致力於以最快的速度抓取目標控件),所以iQuery和jQuery的語法有一些細微的差別。
我們以下面的程序為例說明iQuery的語法和在iOS上的用法:
其對應的控件樹形式為,控件樹和后面的示例圖片都是從HierarchyViewer-4-iOS上獲取的:
HierarchyViewer-4-iOS工具的使用說明請參見文章:
http://www.cnblogs.com/vowei/archive/2012/08/13/2614468.html
其源代碼也是開源的:
https://github.com/vowei/HierarchyViewer-4-iOS
下面是幾個iQuery語法示例,更詳細的示例以及文檔請參考網頁http://www.vowei.com/iquery-1.html):
要在Instrument中使用iQuery,只要在自動化測試用例的腳本中引入iquery.js文件即可,如下所示:
在后面的例子中,下面root和assert是兩個全局變量,root表示當前應用的主窗口。
var root = target.frontMostApp().mainWindow(); var assert = new Assert();
跟jQuery類似,iQuery的查詢操作函數名也是$,函數聲明如下:
$(selector, context)
1、跟jQuery類似,iQuery也可以省略查詢起始的控件位置(即context參數),那樣的話默認從應用的當前窗口開始查詢:
test("([attr (>|<|>=|<=) float])比較屬性值", function() { var query = "> [value >= 59%]"; var result = $(query); assert.Equals(1, result.length); query = "> [:height > 31]"; result = $(query); assert.Equals(6, result.length); for ( var i = 0;i < result.length; ++i ) { assert.True(result[i].rect().size.height > 31); } query = "UIAWindow > UIASegmentedControl > UIAButton :eq(0) + UIAButton"; result = $(query); assert.Equals(1, result.length); assert.Equals("Second", result[0].name()); });
上例中:
$("> [:height > 31]")的意思在默認的當前界面主窗口下,在其子控件列表里查找高度大於31個像素點的控件,其中我們叫它:height 偽屬性,所有在方括號內,以英文冒號開頭的都被稱作偽屬性,為了統一表示多個平台,有些平台例如Android實現了控件的height屬性,而有些平台例如iOS上就沒有實現這個屬性,是通過rect屬性獲取的。為了在多個平台上統一表達這些差異,我們將這些差異抽象成偽屬性的概念。
$("> [value >= 59%]")的意思在默認的當前界面主窗口下,在其子控件列表里查找具有名為“value”的屬性,且其值大於59%的控件。如下圖所示:
$("UIAWindow > UIASegmentedControl > UIAButton :eq(0) + UIAButton")的意思是在指定的上下文控件(即當前窗口對象)中,先匹配類型名為“UIAWindow”的控件也就是窗口對象本身,在其子控件列表中過濾出類型名為“UIASegmentedControl”的控件集中,找出所有類型名為“UIAButton”的子控件數組,接着在數組中獲取第一個子控件(:eq(0))的后面一個名為“UIAButton”的子控件。
2、[iOS]上,針對JavaScript UIA對象,iQuery給每個對象提供了iQuery查詢擴展函數:
test("測試對UIAElement的擴展", function() { var result = root.$("> [value >= 59%]"); assert.Equals(1, result.length); root.logElementTree(); result = root.segmentedControls()[0].$("> :button"); assert.Equals(3, result.length); });
上例演示了針對任意一個UIAElement對象,都有一個擴展的iQuery函數$(query)。
3、再來看看指定iQuery查詢條件“selector”和查詢起始的控件位置“context”的做法:
test("(*)匹配所有元素", function(){ var query = "> *"; var result = $(query, root.navigationBars()[0]); assert.Equals(2, result.length); assert.Equals("UIAStaticText", type(result[1])); query = ">> UIAStaticText:not([name!='TestUIDemo'])"; result = $(query, root); assert.Equals(1, result.length); assert.Equals("TestUIDemo", result[0].name()); });
上例中,“>> UIAStaticText:not([name!='TestUIDemo'])”的意思是從指定的上下文(context)控件root的所有子孫控件集合里,首先過濾出類型名為UIAStaticText的控件列表,再在其中找出所有不滿足name屬性的值不是“TestUIDemo”的控件,如下圖所示:
從前面幾個例子里可以看出,iQuery分為這幾大部分:
以空格分隔的過濾條件默認是交集查詢的方式,即后一個條件在前一個條件過濾后的控件集合里執行過濾操作。這一點跟jQuery的語法是不一致的,在jQuery里,空格分隔的條件是爺孫關系,即前一個條件在爺爺層過濾控件,再在結果控件的子孫控件中匹配空格后的條件。
子孫層次查詢,通過“>”、“>>”等操作符指明過濾的層次。
注意:在iOS平台上,instrument下javascript的API在遍歷控件樹時非常慢,以本文的測試程序為例,從窗口層開始執行全遍歷需要2分鍾左右,因此除非特別有必要,不建議在iOS平台下使用“>>”操作符。
按照任意的控件類型名查詢控件。
注意:在jQuery里,根據控件類型名的查詢是在當前context控件的子孫控件集里查詢的,由於前面描述的原因,iOS上子孫控件的遍歷操作非常慢,因此從代碼執行速度方面的考慮,iQuery只在context控件這一層執行查詢操作,如果要在子孫控件里過濾,必須使用“>”、“>>”和“> num”操作符指明要查詢的控件在控件樹里的層次信息。
#id,按照控件的Id查詢。
注意:按控件id查詢默認是在當前context控件的子孫控件集里查詢的,由於前面描述的原因,iOS上子孫控件的遍歷操作非常慢,因此除非迫不得已,不建議使用。
偽類型,以冒號開頭的類型都是偽類型。iQuery通過將多個平台共有的控件抽象成偽控件,便於對跨平台應用的測試,比如說,幾乎所有的操作系統里都有文本框這個概念,因此使用“:text”這個偽類型就可以表達不同操作系統上的文本框了。
屬性,根據控件自身的屬性值過濾,屬性值支持字符串的比較(如 [attr $= ‘value’] 指查詢屬性“attr”的值以字符串“value”結尾的控件),數字甚至的百分比的比較(如 [attr >= 59%] 指查詢屬性“attr”的值大於59%的控件)。
偽屬性,跟偽類型類似,用來抽象不同平台控件共有的屬性,例如表示控件位置的top、left、right、bottom、width和height之類的屬性。偽屬性支持用戶擴展,即可以在測試用例里注冊一個新的偽屬性,通過提供的自定義過濾函數查詢。
最后,希望iQuery能夠簡化你的自動化測試編寫工作,如果有任何建議,請在iQuery的官方文檔的評論欄(http://www.vowei.com/iquery-1.html)提出你的寶貴意見。