佘學(xué)文 陳向宇 劉東啟
1(廣東嶺南職業(yè)技術(shù)學(xué)院 廣東 廣州 510663) 2(華南理工大學(xué)計(jì)算機(jī)科學(xué)與工程學(xué)院 廣東 廣州 510006)
隨著人工智能和移動(dòng)互聯(lián)網(wǎng)的迅猛發(fā)展,智能手機(jī)已經(jīng)成為人們生活的重要部分。美國(guó)媒體機(jī)構(gòu)Zenith發(fā)布的最新研究報(bào)告顯示, 2018年中國(guó)智能手機(jī)用戶數(shù)達(dá)到13億,位居全球第一,全球智能手機(jī)用戶數(shù)也達(dá)到33億,并且還在逐年增加。圖形用戶界面(Graphical User Interface,GUI)是用戶與手機(jī)應(yīng)用程序(App)進(jìn)行交互的最重要通道。在激烈的市場(chǎng)競(jìng)爭(zhēng)中,高質(zhì)量、無(wú)瑕疵的GUI是一款應(yīng)用程序成功的重要前提,GUI測(cè)試是保證應(yīng)用程序GUI質(zhì)量的重要手段。目前,學(xué)術(shù)界和工業(yè)界已經(jīng)研究、實(shí)現(xiàn)和評(píng)估了多種GUI測(cè)試的方法[1-6],但Joorabchi等[7]一項(xiàng)關(guān)于移動(dòng)App開(kāi)發(fā)面臨的挑戰(zhàn)的研究表明,超過(guò)70%的移動(dòng)應(yīng)用開(kāi)發(fā)或測(cè)試人員在實(shí)踐中傾向于采用手動(dòng)方法進(jìn)行GUI測(cè)試,從事全自動(dòng)GUI測(cè)試的人數(shù)不到5%,超過(guò)一半的參與者認(rèn)為實(shí)現(xiàn)自動(dòng)化GUI測(cè)試是一項(xiàng)具有挑戰(zhàn)性的工作,且移動(dòng)應(yīng)用GUI測(cè)試目前仍然是一項(xiàng)勞動(dòng)密集型工作。
為了提高Android應(yīng)用GUI測(cè)試的效率和自動(dòng)化水平,本文建立一套易于實(shí)現(xiàn)、開(kāi)展測(cè)試的前置條件簡(jiǎn)單且更加高效的Android應(yīng)用GUI自動(dòng)化隨機(jī)測(cè)試方法,該方法在開(kāi)展測(cè)試前只需要簡(jiǎn)單的準(zhǔn)備工作,同時(shí)采用以下手段來(lái)保證更好的代碼覆蓋率:
1) 在測(cè)試時(shí)通過(guò)映射GUI樹(shù)和行為樹(shù)模型來(lái)避免靜態(tài)分析。
2) 動(dòng)態(tài)更新模型以增加用戶在使用應(yīng)用程序過(guò)程中很少或從未使用過(guò)的事件的概率。
3) 應(yīng)用統(tǒng)計(jì)模型建立行為樹(shù)模型。
目前,工業(yè)界和學(xué)術(shù)界已經(jīng)在Android應(yīng)用GUI自動(dòng)化測(cè)試方面開(kāi)展了許多工作。Google提供的Android SDK中,給出了三種可用于自動(dòng)化測(cè)試的方式,即Monkey、MonkeyRunner和Instrumentation。其中Monkey[3]是測(cè)試Android應(yīng)用程序最常用的工具,它通過(guò)向系統(tǒng)發(fā)送偽隨機(jī)的用戶事件流(如按鍵輸入、觸摸屏輸入、手勢(shì)輸入等)對(duì)被測(cè)應(yīng)用程序(Application Under Test ,AUT)進(jìn)行有效的自動(dòng)化測(cè)試。但Monkey自動(dòng)生成的大量輸入很簡(jiǎn)單,無(wú)法生成需要人類智能組合的測(cè)試輸入,且會(huì)生成很多冗余輸入。文獻(xiàn)[4-5]采用了基于Hook機(jī)制的GUI自動(dòng)化測(cè)試方法。文獻(xiàn)[8]采用的基于隨機(jī)探索的方法。文獻(xiàn)[9]采用了基于模型(MBT)的方法并研制了工具AndroidRipper。該工具維護(hù)一個(gè)GUI狀態(tài)機(jī)模型,在執(zhí)行測(cè)試過(guò)程中,AndroidRipper通過(guò)深度優(yōu)先搜索(DFS)策略動(dòng)態(tài)分析GUI的控件獲取其可觸發(fā)的事件序列,每一個(gè)事件序列就是一個(gè)測(cè)試用例。文獻(xiàn)[10-11]提出基于捕獲用戶輸入的GUI自動(dòng)化測(cè)方法,其中文獻(xiàn)[11]創(chuàng)建了一個(gè)名為MonkeyLab的工具,該工具通過(guò)挖掘GUI的模型為自然和非自然事件序列生成可操作的場(chǎng)景。
本文提出的基于行為樹(shù)模型的GUI自動(dòng)化隨機(jī)測(cè)試方法的創(chuàng)新之處在于開(kāi)展測(cè)試的前置準(zhǔn)備過(guò)程簡(jiǎn)單,且測(cè)試過(guò)程中會(huì)動(dòng)態(tài)更新行為樹(shù)模型以增加測(cè)試覆蓋率。初始行為樹(shù)模型是通過(guò)統(tǒng)計(jì)建模從使用日志中創(chuàng)建的,考慮到Android應(yīng)用的部分事件可能在使用日志中沒(méi)有出現(xiàn)過(guò),提出通過(guò)將行為樹(shù)模型中的事件映射到GUI樹(shù)中的控件來(lái)解決,同時(shí)行為樹(shù)模型中事件的概率也隨著測(cè)試的進(jìn)行而動(dòng)態(tài)調(diào)整。圖1為本文方法的總體框架,主要分為六個(gè)步驟。
圖1 方法總體框架
1) 從使用記錄器中預(yù)先收集使用日志,并利用Hierarchy Viewer從AUT中提取GUI樹(shù)。
2) 應(yīng)用統(tǒng)計(jì)模型創(chuàng)建行為樹(shù)模型,然后將行為樹(shù)模型中的事件映射到GUI樹(shù)中的控件,以便根據(jù)要執(zhí)行事件序列,自動(dòng)進(jìn)行GUI控件操作,實(shí)現(xiàn)GUI的自動(dòng)化測(cè)試。
3) 從行為樹(shù)模型中隨機(jī)選擇事件,生成執(zhí)行事件序列。
4) 將所選事件觸發(fā)到AUT。
5) 對(duì)使用日志進(jìn)行日志分析,根據(jù)分析結(jié)果得到用戶執(zhí)行某事件的頻率,并根據(jù)事件頻率調(diào)整概率,動(dòng)態(tài)更新行為樹(shù)模型。
6) 重復(fù)步驟2)至步驟5)直到達(dá)到時(shí)間限制或預(yù)先確定的事件數(shù)量。
此步驟的目的是獲取用于生成行為樹(shù)模型的控件、使用日志和GUI樹(shù)。
2.1.1使用日志獲取
獲取使用日志是本文方法開(kāi)展測(cè)試的唯一前置條件和步驟。使用日志是通過(guò)使用記錄服務(wù)Recorder從AUT獲得的。Recorder服務(wù)使用Android的AcciblityService實(shí)現(xiàn),該服務(wù)以AccessibilityEvent的形式捕獲測(cè)試人員或用戶執(zhí)行的事件,然后收集這些事件并通過(guò)Android調(diào)試橋(Android Debug Bridge,ADB)傳輸?shù)絆bserver。如表1所示的事件,如果Recorder服務(wù)開(kāi)啟,那么一旦用戶開(kāi)始使用應(yīng)用程序,Recorder服務(wù)就會(huì)記錄用戶的使用日志,直到用戶關(guān)閉該應(yīng)用程序。由于這些使用日志是建立行為樹(shù)模型的基礎(chǔ),因此覆蓋的使用場(chǎng)景越多越好,測(cè)試方可以通過(guò)眾包的方式獲得大量使用日志數(shù)據(jù)。
表1 AccessibilityEvent定義的幾種事件類型
續(xù)表1
2.1.2從AUT中提取GUI樹(shù)
GUI樹(shù)是GUI控件的層次結(jié)構(gòu),在運(yùn)行時(shí)使用Android SDK工具包中的可視化調(diào)試工具Hierarchy Viewer從AUT中提取。Hierarchy Viewer 通過(guò)ADB與 Android 模擬器或 Android 真機(jī)進(jìn)行通信,可以列出應(yīng)用程序的樹(shù)形結(jié)構(gòu)布局,并提供所有 GUI 控件的ID、控件類型、文本內(nèi)容、位置和大小等信息。本文使用圖2所示的圖片編輯程序來(lái)作為測(cè)試樣例進(jìn)行說(shuō)明,圖3顯示了圖2中示例活動(dòng)的簡(jiǎn)化GUI樹(shù)。在這個(gè)例子中,簡(jiǎn)化的GUI樹(shù)包括6個(gè)GUI 控件:e1.backButton、e2.editButton、e3.deleteButton、e4.shareButton、e5.imageView和e6.saveButton 。
圖2 樣例AUT(圖片編輯程序)
圖3 AUT的GUI樹(shù)
在這個(gè)步驟中,根據(jù)使用日志創(chuàng)建行用戶執(zhí)行事件的行為樹(shù)模型,然后將事件映射到GUI樹(shù)中的GUI 控件。
2.2.1行為樹(shù)模型生成
通過(guò)使用馬爾可夫假設(shè)近似條件概率從使用日志創(chuàng)建行為樹(shù)模型(如圖4中的簡(jiǎn)化行為樹(shù)模型)。
圖4 簡(jiǎn)化的行為樹(shù)模型
本文使用N-gram語(yǔ)言模型來(lái)實(shí)現(xiàn),N-gram 是一種基于統(tǒng)計(jì)語(yǔ)言模型的算法,又被稱為一階馬爾可夫鏈,它的基本思想是將文本里面的內(nèi)容按照單詞進(jìn)行大小為N的滑動(dòng)窗口操作,形成長(zhǎng)度是N的單詞片段序列。在軟件測(cè)試的背景下,這些單詞代表事件,n表示事件的數(shù)量。例如,一系列事件etap1,etap2,ehold1,eswipeUp,如果設(shè)n=2,那么2-gram為:
1)p(etap2|etap1)
2)p(ehold.1|etap2)
3)p(eswipeUp|ehold.1)
如果設(shè)n=3,那么3-gram為:
1)p(ehold.1|[etap1,etap2])
2)p(eswipeUp|[etap2,ehold.1])
其中,p(ex|[ej,ek])是在給定歷史事件[ej,ek]下選擇事件ex的概率,當(dāng)n較大時(shí),模型可以存儲(chǔ)更多上下文,從而可以更加充分地進(jìn)行時(shí)空權(quán)衡。在實(shí)際中,用戶的使用范圍可能無(wú)法完全覆蓋應(yīng)用程序的所有功能。在圖4中,假設(shè)當(dāng)用戶處于活動(dòng)B時(shí),可能發(fā)生另一個(gè)事件e6,但簡(jiǎn)化的行為樹(shù)模型中沒(méi)有該事件,這意味著模型未對(duì)程序的事件實(shí)現(xiàn)完全覆蓋,且事件e6永遠(yuǎn)不會(huì)被映射、選擇和執(zhí)行。因此,將GUI樹(shù)中可用、但在模型中不存在的事件稱為未知事件。
為了解決這個(gè)問(wèn)題,需要調(diào)整概率分布。常用的N-gram訓(xùn)練工具有SRILM、IRSTLM、BerkeleyLM和KenLM等[12-14],這幾種工具所用的算法思想基本一致,本文以KenLM(速度最快,占用內(nèi)存最少)作為訓(xùn)練工具,所用的平滑技術(shù)是Modified Kneser-ney smoothing[15]。因?yàn)樗徽J(rèn)為是當(dāng)前一個(gè)標(biāo)準(zhǔn)的、廣泛采用的、效果最好的平滑算法,Modified Kneser-ney smoothing平滑技術(shù)有三個(gè)核心思想。
1) 絕對(duì)折扣。為了給未知事件一些概率,必須降低其他事件的概率,以保持有效的概率分布。
2) 插值。遞歸地組合所有k-gram的概率,其中k∈1,2,…,n,如果一個(gè)事件序列在模型中出現(xiàn)任何k-gram下標(biāo),那么它將產(chǎn)生非零概率。
3) 歷史。應(yīng)該考慮每個(gè)事件出現(xiàn)的上下文的數(shù)量。例如,如果一個(gè)事件只發(fā)生在特定的上下文中,那么它就不太可能出現(xiàn)在新的上下文中。
2.2.2將行為樹(shù)模型映射到GUI樹(shù)
行為樹(shù)模型中的每個(gè)事件都使用唯一的resource-id作為鍵映射到GUI樹(shù)中的GUI控件,如果沒(méi)有定義resource-id,則使用類型和文本映射到GUI控件。為了提高查找速度,本文使用哈希表實(shí)現(xiàn)GUI映射器,并在每次重新獲取使用日志信息后進(jìn)行更新。
本文的目的是測(cè)試應(yīng)用程序,而不是創(chuàng)建一個(gè)自然的動(dòng)作序列,因此,動(dòng)作序列中的下一個(gè)事件并不會(huì)簡(jiǎn)單地依據(jù)概率的高低選擇,而是隨機(jī)選擇。設(shè)e1,e2,…,en∈{possibleEvents},且h是先前選擇的歷史事件,事件選擇器將根據(jù)給定的一系列先前所選事件的平滑概率來(lái)隨機(jī)選擇enext:
enext=w([p(e1|h)],[p(e2|h)],…,
[p(en|h)])
(1)
圖5 平滑后的行為樹(shù)模型
Event Executor執(zhí)行由事件選擇器在實(shí)際移動(dòng)設(shè)備或仿真器上通過(guò)UI Automator選擇的enext,本文方法可以執(zhí)行諸如單擊、長(zhǎng)按、滾動(dòng)和文本編輯等事件,這些事件定義如下:
單擊:點(diǎn)擊并立即在視圖中釋放。
長(zhǎng)擊:在視圖點(diǎn)擊并按住3 s后釋放。
滾動(dòng):點(diǎn)擊并拖動(dòng)到x+Δx,y+Δy位置。
文本編輯:輸入任意的預(yù)生成的字符串。
假設(shè)enext為圖4中的e6,并且是可點(diǎn)擊的,Event Executor將向視圖的中心觸發(fā)一個(gè)單擊事件,在這種情況下,本例中為saveButton。
執(zhí)行后,利用偏置隨機(jī)技術(shù)對(duì)模型進(jìn)行更新,以調(diào)整所選擇/執(zhí)行的事件的概率,它減少了先前選擇和執(zhí)行的事件的小因子。
p′(ex|h)=p(ex|h)-d(ex,δfx)
(2)
式中:fx是ex的頻率,d(ex,δfx)是ex的折扣值,p(ex|h)是給定歷史事件h下事件ex發(fā)生的概率。假設(shè)d(e6,δf6)=0.005,那么根據(jù)式(2)可以得到p′(e6|h)=0.025,在從ex中減少一些概率之后,必須重新計(jì)算每個(gè)p′的概率,以便通過(guò)將其除以總p′概率來(lái)保持有效的概率分布。
(3)
式(3)的結(jié)果如圖6所示。p(e6|h)的概率降低了,但p(e1|h)至p(e5|h)略有增加,這將使其他事件有更大的機(jī)會(huì)被選擇,從而提高代碼覆蓋率。最后,在執(zhí)行e6后更新器更新行為樹(shù)模型。
圖6 更新后的行為樹(shù)模型
為了評(píng)估本文方法的有效性,將其與另外三種主流的方法進(jìn)行比較:Android Monkey、手動(dòng)測(cè)試和Dynodroid工具。評(píng)估采用的目標(biāo)程序是三個(gè)未經(jīng)修改的開(kāi)源Android應(yīng)用程序:Anymemo[16]、World Clock[17]和Weight Chart[18]。這三款工具分別具有動(dòng)態(tài)內(nèi)容、靜態(tài)內(nèi)容和復(fù)雜的用戶界面,可以在一定程度上保證評(píng)估的覆蓋面和可信性。
表2 性能評(píng)估程序
所有的實(shí)驗(yàn)都使用Android API 19在Nexus 5模擬器上完成的,該模擬器具有1 586 MB的RAM,運(yùn)行在64位Windows 7計(jì)算機(jī)上,具有3.1 GHz的i7處理器和16 GB的RAM。讓5個(gè)學(xué)生分別使用5分鐘上述應(yīng)用程序來(lái)獲取使用日志,對(duì)他們?nèi)绾问褂眠@些應(yīng)用程序沒(méi)有任何限制,且每次實(shí)驗(yàn)AUT都安裝在新創(chuàng)建的模擬器上,同時(shí)只使用默認(rèn)設(shè)置。每一次實(shí)驗(yàn),根據(jù)本文方法開(kāi)發(fā)的工具、Android Monkey和Dynodroid都包含5 000個(gè)觸摸事件,為了確保每次執(zhí)行下一個(gè)事件之前完成屏幕切換或動(dòng)畫(huà),在每個(gè)事件之間設(shè)置500 ms的延時(shí)。對(duì)于手動(dòng)測(cè)試,要求測(cè)試人員在40 min內(nèi)盡可能多地手動(dòng)執(zhí)行這些應(yīng)用程序。在每次實(shí)驗(yàn)后都會(huì)重置模擬器以防止它影響后續(xù)的測(cè)試,同時(shí)使用EMMA覆蓋率檢測(cè)工具[19]和自定義shell腳本從AUT收集覆蓋率信息。
在每個(gè)程序設(shè)置了10個(gè)數(shù)據(jù)采集點(diǎn),每500次事件間隔讀取一次代碼覆蓋率,測(cè)試結(jié)果如表3所示。Our_COV代表本文方法的覆蓋數(shù)據(jù),Monkey_COV代表Android Monkey的覆蓋數(shù)據(jù),Dynodroidy_COV代表Dynodroidy的覆蓋數(shù)據(jù),Manual_COV代表人工手動(dòng)測(cè)試的覆蓋數(shù)據(jù),表中的數(shù)字表示每種方法所覆蓋的代碼行數(shù)和代碼覆蓋率。測(cè)試結(jié)果表明,在Anymemo中,本文方法的性能優(yōu)于Android Monkey和Dynodroid,但是沒(méi)有手動(dòng)測(cè)試好。在3個(gè)應(yīng)用程序測(cè)試中,人工手動(dòng)測(cè)試的代碼覆蓋率均是最高的,這是可以預(yù)見(jiàn)的,因?yàn)槿祟惪梢蕴峁└悄艿奈谋净蝽樞蜉斎搿?/p>
表3 四種測(cè)試方法代碼覆蓋率對(duì)比
圖7顯示了Anymemo的累積代碼覆蓋率。X軸表示基于500個(gè)事件間隔的事件數(shù)量。為了不在測(cè)試期間干擾受試者,在手動(dòng)測(cè)試期間沒(méi)有記錄覆蓋率,所以手動(dòng)測(cè)試的數(shù)據(jù)為最終覆蓋率。
圖7 Anymemo的累積代碼覆蓋率
本文介紹了一種基于行為樹(shù)模型的Android應(yīng)用GUI自動(dòng)化隨機(jī)測(cè)試方法。該方法基于實(shí)際使用日志創(chuàng)建行為樹(shù)模型,在運(yùn)行時(shí)用GUI樹(shù)映射行為樹(shù)模型,用改進(jìn)的Kneser-Ney平滑技術(shù)處理零概率未知事件。為了評(píng)價(jià)本文方法的有效性,設(shè)置了實(shí)驗(yàn),通過(guò)3個(gè)開(kāi)源應(yīng)用程序與Android Monkey、手動(dòng)測(cè)試、Dynodroid等方法進(jìn)行了對(duì)比。測(cè)試結(jié)果表明,本文方法在所有應(yīng)用程序上都優(yōu)于Android monkey,在Anymemo、World Clock上優(yōu)于Dynodroid,但是落后于手動(dòng)測(cè)試。未來(lái),將擴(kuò)展本文方法能夠處理的可操作事件,如縮放、拖拽等。同時(shí)通過(guò)更復(fù)雜的Android應(yīng)用程序來(lái)評(píng)估本文提出的工具。