陸一飛, 潘敏學, 張 天, 王林章, 李宣東
(計算機軟件新技術國家重點實驗室(南京大學),江蘇 南京 210023)
隨著智能機與平板電腦的日漸普及,安卓設備及其應用市場蓬勃發展.近年來,在谷歌公司的推廣下,安卓(Android)這一開源操作系統被廣泛應用于移動智能終端.根據Gartner 公司的調研[1],截至2018 年第一季度,安卓系統在智能手機市場的占有率已經達到85%.此外,至2018 年6 月,單在Google Play 應用商店中可獲得的安卓應用已超過330 萬[2].毫無疑問,安卓設備以及安卓應用已逐漸成為移動計算市場的主流.安卓應用在擁有越來越豐富功能的同時,還需要應對各種各樣的操作環境的變化[3],導致其應用復雜度也呈現指數級的增長.同時,為了能更好地搶占市場,安卓應用需要適配盡可能多的設備和系統版本.而其多樣化和碎片化,使得同一個應用經常需要開發多個版本,用于適配不同版本的安卓系統和設備.這些因素綜合在一起,使得相應的開發與測試中的工作量大為增加.
針對上述問題,模型的使用是一種比較常見的方式.通過模型來描述并設計安卓應用,可將原本繁瑣的應用主體分解為不同的模塊逐個處理,降低了開發的整體難度.模型的使用可以將安卓應用中設備、系統版本相關和無關的部分相分離,使得應用的邏輯設計這一類不因設備和系統版本變化的部分得到充分復用,避免重復開發.目前,國際上已有學者將各類模型應用于安卓應用的設計和開發.Parada 等人采用UML 類圖和時序圖作為移動應用的高層抽象模型,并基于這些模型實現了代碼的部分自動化生成[4];Heitk?tter 等人針對數據驅動應用,基于md2這一MVC 結構模型進行移動端的模型驅動開發[5].然而,這些模型都是為傳統的桌面應用設計,沒有考慮安卓應用本身的特點.與傳統的桌面應用不同,安卓應用由事件驅動,大量依賴于圖形化用戶界面(GUI)[6],這就需要有能夠有效對GUI 進行建模的語言.交互流建模語言(interaction flow modeling language,簡稱為IFML)[7]作為面向對象組織OMG 的年輕標準,倡導以圖形的形式描述軟件系統前端設計中的展現內容及與用戶之間的交互.它能夠與其他基于UML 的模型兼容,有良好的可擴展性與兼容性.它以事件流為驅動,重視用戶、系統事件以及人機交互,能夠有效地應對安卓應用基于GUI 的事件驅動特性.因此,本文將研究基于IFML 對安卓應用建模的方法.
根據用戶的需求,在設計階段,面向安卓應用建立的IFML 模型,能夠有效地描述安卓應用中極為重要的GUI 結構以及各GUI 元素間的交互關系,即工作流的傳遞,并利用其強大的表達能力促進開發人員對應用設計的認識,指導開發工作系統、有效地進行,減少理解誤區.此外,IFML 模型所包含的豐富語義使得依據該模型進行的測試效果極為有效.這些測試的執行能夠保證應用實現與設計,即IFML 模型保持一致,從而保證開發質量.同時,在應用的演化過程中,開發人員可以通過增量式修改IFML 模型來驅動演進工作的進行.在已建立IFML模型的基礎上,開發人員僅需要低額的工作量便可完成其上的修改工作,這使得IFML 建模的初期成本被不斷稀釋.該IFML 模型還擁有廣泛的應用前景,通過提高自動化的方式,無論是代碼的自動化生成還是測試的自動化生成與執行,都能有效地減少開發成本,提高開發效率.然而當前的IFML 廣泛應用于多平臺應用的建模,在描述安卓應用時太過寬泛,對安卓應用端特有元素的描述能力較為欠缺,因此將IFML 應用于安卓應用開發的效果將大打折扣.為此,本文研究了IFML 面向安卓端的擴展,以此提高IFML 對安卓應用的描述能力.基于該擴展后的IFML,使用者能夠建立與安卓應用更加契合的模型,用于安卓應用的設計、開發和持續發展.
本文的工作與貢獻主要包括4 個方面.(1)本文提出了面向安卓平臺的IFML 擴展,以更好地對安卓應用進行IFML 建模.(2)對于IFML 標準中非形式化的部分及本文提出的擴展部分,我們都給出了形式化的定義,為基于IFML 模型的各類開發和測試方法奠定了理論基礎.(3)探索了面向安卓端的IFML 的應用前景,針對安卓應用的測試需求開發了基于IFML 模型的安卓應用的建模與測試工具ADAMANT.利用該工具,使用者可以以圖形化的方式建立IFML 模型,并利用模型生成測試用例并執行.(4)基于ADAMANT,本文為當前5 個真實的安卓應用進行了IFML 建模,并基于模型對應用進行了測試.其良好的測試結果表明了將IFML 應用于安卓應用的建模以推進開發工作這一方法的可行性.
本文第1 節從總體上介紹IFML 及其特點,并簡要介紹其主體組成結構.第2 節以一個安卓應用為例描述當前IFML 在描述安卓應用時的不足,說明擴展IFML 以用于安卓應用開發工作的必要性.第3 節有針對性地對IFML 進行安卓平臺的擴展,并對擴展后的IFML 模型進行實例描述.第4 節在第3 節的基礎上,提出擴展后的IFML 模型,以及模型中執行語義的形式化定義.第5 節介紹本文實現的建模與測試工具ADAMANT,并將其應用于5 個安卓應用之上,用于探索面向安卓應用的IFML 擴展在指導應用開發過程中的可行性.第6 節探討并比較在移動應用中使用模型輔助開發、測試,以及對IFML 擴展這3 方面的已有工作.第7 節總結全文,提出未來的研究方向和改進目標.
交互流建模語言IFML 是以圖形的形式描述軟件系統前端設計中的展示內容、與用戶之間的交互以及行為控制等內容的可視化建模語言[7].它在2013 年被OMG 協會納為標準,并在2015 年發表了1.0 官方正式文檔.

Table 1 The introduction to commonly used elements of IFML model表1 IFML 模型中常用元素簡介
IFML 的主要目的在于提供軟件工程師們用以描述圖形化界面應用前端的IFML 模型(IFMLModel),它可以支持諸如桌面應用、網頁應用等等多種終端上的應用,具有較強的泛用性.IFML 模型以樹狀結構抽象代表了應用中各前端元素,以及各元素之間的交互關系.本文在表1 中對IFML 模型中的常用元素進行了介紹.
大體而言,IFML 模型中存在多個視圖容器,代表應用或系統中的界面.每個視圖容器可以擁有屬于自己的視圖組件來表示該界面上的控件元素.在視圖組件上又可包含視圖組件部件來對該視圖組件進一步補充說明.視圖容器和視圖組件可以擁有參數元素來輔助表示模型的狀態,并且參數的數值可參與表達式的計算,其計算結果用于模型內的邏輯判斷.此外,視圖容器、視圖組件或視圖組件部件也可持有事件元素.當事件被觸發時,交互流會從該事件導出,傳遞給其他元素,用于表示視圖焦點或是數據的轉移.與此同時,交互流上的參數綁定組將會進行參數的傳遞.特別地,當導向流指向行為元素時,行為所代表的業務邏輯將會被執行,完成后將會觸發其上的行為事件,從而引出新的交互流指向其他元素.
本節將介紹一個來自Github 上的安卓開源應用Good Weather,并使用標準的IFML 為其建模.Good Weather用于展示當地的天氣信息,該應用可在Github、Google Play 及F-droid 上獲取.

Fig.1 Three views of Good Weather and their relations圖1 Good Weather 應用的3 個視圖及它們之間的關系
圖1 顯示了Good Weather 這一安卓應用的GUI 視圖,以及各視圖之間的跳轉關系.其中,圖1-2 為Good Weather 應用的主界面.它顯示了選定城市的天氣與相關環境信息.通過點擊右上角的3 個圖標按鈕可以分別對天氣進行刷新、對城市進行文本搜索(如圖1-3 所示)以及進行GPS 位置搜索.在主界面中,也可通過向右滑動打開其側邊欄(如圖1-1 所示),點擊其中的Setting、Feedback 以及Donate Bitcoin 文本,也可分別打開設定、反饋以及捐款頁面.
圖2 顯示的是本文為Good Weather 應用建立的IFML 模型中的主界面和側邊欄部分(如圖1-2 和圖1-1 所示).在該IFML 模型中,本文以視圖容器(白色方角框)來表示主界面、工具欄以及側邊欄這類整體的界面.在這些視圖容器中,我們以視圖組件(灰色圓角框)來表示文本、圖片、圖標以及按鈕這些控件,它們可觸發相應的事件(圖中白色小圓圈),引起交互流的傳遞.如HomeButton 這一視圖組件代表了主界面左上角的按鈕,其上的事件touch the button,表示用戶在點擊這一按鈕時將會將交互流導向SideBar 這一容器,即應用的側邊欄.此外,該模型中也以參數isLocated 來表示該應用當前是否進行了定位,使用激活表達式來判斷是否根據isLocated 的值來顯示詳細的天氣信息,并在行為locating 的執行中會動態地修改isLocated 的值(其具體執行過程由UML 動態模型表示).此過程中IFML 原有的模型元素概念太過寬泛,不足以精確描述安卓應用中的獨有元素,具體有以下3 類.
1)豐富的界面元素.安卓設備較小的設備屏幕,無法同時容納大量的控件元素,因而需要多個界面來協同完成應用的功能.為此,諸如工具欄、側邊欄等僅占據屏幕一部分的輕量級界面容器被廣泛應用于界面間的跳轉或導航.它們與占據應用整個屏幕的、用于實現應用主功能的各個界面,在外觀和使用方式上都存在較大的差異,無法由IFML 中原有的視圖容器和視圖組件進行有效區分.而對于安卓端的控件,諸如文本、按鈕、圖片等諸多元素,它們的外形以及其上可觸發的事件各異(如文本和按鈕上通常可以進行長按、點擊操作,而圖片則通常可以進行滑動、縮捏操作等等),以原IFML 中的視圖容器和視圖組件統一地表示這些元素可能會引起設計和實現中的誤解,為此,我們需要對IFML 中的視圖容器和視圖組件進行擴展,進而有效地區分這些容器和組件.
2)多樣的用戶手勢.眾所周知,安卓應用也支持多樣的用戶手勢,如點擊、長按、滑動等.同時,在同一個控件上,不同的手勢操作通常會引起不同的事件行為.例如,在文件管理類應用中,對于以列表形式出現的文件列,普通的點擊操作將會打開該文件的詳細信息界面,而長按操作則會彈出文件的操作菜單,包含刪除、移動、詳情等等.原IFML 僅以事件下的子類型、視圖元素事件(ViewElementEvent)來進行統一的表示.因此,在上述的IFML 模型中,為了區分各事件所代表的具體操作行為,仍需要使用自然語言來進行輔助說明.這一方式不但建模時存在不便,而且在設計和實現時也可能會引入歧義.為此,對于安卓用戶手勢的擴展也勢在必行.
3)繁多的系統事件.同時,由于安卓設備便攜的特點,安卓應用往往還需處理多樣的系統事件,如電量變化、網絡連接、GPS 定位、傳感器感知等類型的事件.在IFML 中,它們都由事件下的子類型系統事件(SystemEvent)來統一表示.這樣的表示方式也過于籠統,因此,本文也對安卓端的系統事件進行了擴展.

Fig.2 A part of IFML model for Good Weather圖2 Good Weather 應用的部分IFML 模型
綜上所述,本文擬對IFML 標準進行面向安卓端的擴展,從而將IFML 模型應用于安卓應用的建模,在應用的演進過程中持續性地指導應用的設計與實現工作.
由于原IFML 在用于安卓應用建模時存在種種不足,本文認為需要對IFML 進行面向安卓端的擴展.為此,本文以安卓官方指導文檔為基礎,并以當前安卓應用中的主流常用元素作為補充,提出了以下3 個方面的安卓端擴展:(1)對視圖容器與視圖組件的擴展;(2)對表達式和行為的擴展;(3)對事件的擴展.
視圖容器代表的是一個整體性的界面,本文為其添加了安卓應用視圖容器(AndroidAppContainer)作為安卓端應用中使用的視圖容器子類型,并在其下添加滑動窗口(scroller)、抽屜(drawer)、屏幕(screen)、工具欄(toolbar)和網頁(Web)這5 個實例子類型.滑動窗口表示可上下或左右滑動的視圖容器;抽屜是指可從左/右滑出的側邊欄;工具欄表示應用中具有導航或顯示標題等輔助功能的工具欄容器;網頁則表示以網頁風格展示的視圖容器;屏幕表示應用中進行主體的信息展示,與用戶交互的整體性界面容器,與其他4 個元素進行區分.通過對這些安卓常用視圖容器的特例化,使得建模更加便捷的同時有效區分了各類常用元素.其具體關系結構可如圖3 所示.

Fig.3 The Android extension to ViewContainer圖3 視圖容器的安卓端擴展
視圖組件代表的是視圖容器中用于展示信息或接受輸入的、并可引發應用事件的組件.IFML 標準中所有的組件均以視圖組件來表示,過于籠統.本文為其添加安卓應用視圖組件(AndroidAppComponent)這一子類型表示安卓應用中使用到的視圖組件,并給出了以下更加具體的視圖組件實例:按鈕(Button)表示按鈕類型的組件,其下有子類型:狀態改變按鈕(CompoundButton)表示會引起狀態切換的按鈕;文本(Text)表示文本類型的組件;圖標(Icon)表示圖標組件;圖片(Image)表示圖片組件;編輯框(EditText)表示為文本輸入框;進度條(ProgressBar)表示為進度條組件.本文還添加了模板自定義組件(CustomComponent)允許用戶自定義使用到的組件類型.其具體的關系結構可如圖4 所示.

Fig.4 The Android extension to ViewComponent圖4 視圖組件的安卓端擴展
此外,針對安卓系統上一些獨有的界面元素,相應地,本文使用安卓系統視圖容器(AndroidSystemContainer)與安卓系統視圖組件(AndroidSystemComponent)來表示.本文亦在其下創建了一組實例:通知區域(Notification Area)表示安卓應用中的通知欄區域元素,通知(Notification)表示其中的通知提示信息.該組實例能夠簡化建模過程,并且由于安卓系統中通知區域的唯一性,該組實例能夠與之對應.
表達式定義了一個無副作用的語句,可以在執行后返回特定的結果,以便IFML 模型進行邏輯判斷.在IFML標準中存在多種表達式的實用子類型,在本文中主要使用并介紹其中兩類:交互流表達式,用于判斷對應的事件在當前狀況下最終觸發了哪些交互流;激活表達式,用于判斷該表達式所屬元素是否可見/可觸發.本文還額外定義了兩種表達式,來輔助進行IFML 模型中的邏輯判斷,分別是:
(1)定義表達式新的子類型,默認表達式(DefaultExpression).作為表達式邏輯中重要的參與元素,參數持有一個默認表達式類型的屬性defaultValue,它將賦予該參數的最初值.然而,原IFML 中并未定義其對應的表達式子類型,為此,本文添加了該默認表達式,專門用于以表達式形式直接賦予參數以最初的數值.
(2)定義有副作用的,即計算時可以修改參數數值的新表達式子類型,執行表達式(ExcutionExpression).在原IFML 中,行為用于表示由事件所引起的事務邏輯.其具體執行需要借用UML 活動圖等動態模型來表示.然而,對于通常的安卓應用開發來說,多個模型的使用以及模型間的頻繁切換太過繁瑣.為此,本文在行為下添加一個執行表達式類型的成員executionContent,來輕量級地描述某行為中的具體邏輯.通過執行executionContent可以修改部分參數的數值,表示行為所代表的業務邏輯對模型狀態的影響.
此外,安卓終端也有許多諸如通話、攝像、照相等設備獨有的行為,本文也為其進行了安卓終端的擴展:擴展了安卓行為(AndroidAction),用以表示安卓應用中所引發的事務邏輯,并添加了安卓行為事件(Android Action Event)與之對應,表示為安卓行為執行結束后所觸發的行為事件.同時,本文添加了相機行為(Camera Action)和相機行為事件(CameraActionEvent)這一對實例,用于表示照相/錄像的行為以及對應的行為事件;類似地,還有話筒行為(MicrophoneAction)與話筒行為事件(MicrophoneActionEvent),此處不再一一詳述.這些安卓行為能夠與安卓上的特有行為相對應,簡化對該類復雜行為進行的繁雜建模過程,提高了模型的可用性.
除了第3.2 節中擴展的行為事件外,在第2 節中,我們提及原IFML 用視圖元素事件與系統事件分別表示安卓應用中豐富的用戶手勢和安卓系統所引起的繁多的事件.為此,本文也對這兩類事件進行了擴展.
本文首先在系統事件下擴展了新的子類型:安卓系統事件(AndroidSystemEvent)用于表示安卓終端上系統產生的事件,同時還在該類型下添加了5 個實用子類型:電池事件(BatteyEvent),表示電池狀況所引起的系統事件;存儲事件(StorageEvent),表示系統存儲引起的系統事件;傳感器事件(SensorEvent),表示安卓終端傳感器產生的系統事件;通知事件(NotificationEvent),表示安卓終端的信息通知產生的系統事件;連接事件(Connection Event),表示系統連接產生的系統事件,最終的擴展結構可如圖5 所示.

Fig.5 The Android extension to SystemEvent圖5 系統事件的安卓端擴展
同時,我們還對其中的連接事件和傳感器事件作了進一步的劃分:連接事件可繼續劃分為5 個子類型:藍牙事件(BlueToothEvent)、NFC 事件(NFCEvent)、WiFi 連接事件(WifiEvent)、P2P 事件(P2PEvent)以及USB 事件(USBEvent);而傳感器事件則可細分為 3 個類型:運動傳感器事件(MotionSensorEvent)、環境傳感器(Environment SensorEvent)和位置傳感器事件(PositionSensorEvent),其下可繼續進行劃分,這里不再詳細描述.
安卓端提供了通過壓力和電容感知對屏幕的觸摸捕捉的支持,與PC 的鼠標和鍵盤控制相比有著更豐富的動作與手勢.為此,本文為視圖元素事件添加子類型:安卓視圖元素事件(AndroidElementEvent)表示安卓終端上用戶交互所觸發的事件,在其下還增加了8 個實用子類型:觸摸事件(TouchEvent),表示用戶輕量級觸摸屏幕觸發的事件;雙擊事件(DoubleTapEvent),表示用戶在屏幕同一處位置快速點擊兩次所觸發的事件;長按事件(Long PressEvent),表示用戶長按所觸發的事件;縮捏事件(PinchEvent),表示用戶在屏幕上觸摸由外向內縮捏或由內向外伸展的行為所觸發的事件;滑動事件(SwipeEvent),表示用戶左右滑動所觸發的事件;滾動事件(ScrollEvent),表示用戶上下滑動所觸發的事件;輸入事件(OnInputEvent),表示為用戶進行文本輸入的事件;拖拽事件(Drap DropEvent),表示為用戶拖拽行為觸發的事件.同時,與第3.1 節中自定義組件相對應,本文也建立了自定義事件(CustomEvent)模板,可供用戶自定義可觸發的事件以及具體的觸發行為.最終的擴展結構可如圖6 所示.上述事件的安卓擴展,不僅方便了建模過程,還對執行該事件所可能需要的參數進行了限制,初步進行了標準化,給IFML 建模帶來極大的方便的同時減少了用非形式化語言描述時可能引起的歧義.

Fig.6 The Android extension to ViewElementEvent圖6 視圖元素事件的安卓端擴展
仍以第2 節中驅動案例Good Weather 為例,使用該擴展后的IFML 為其建模也會更加準確.圖7 展示了最終建立的擴展后的IFML 模型,并在各元素附近進行了標號.
對于圖1-1 中Good Weather 所擁有的主界面,我們以擴展后的屏幕元素來表示,即圖中WeatherMainScreen元素(vc1),在開發中它對應于一個Activity(安卓中最基本的活動應用組件).隨后可以看到主界面上存在大量的控件用于顯示天氣信息,在IFML 模型中,我們將這些控件整合起來,使用特殊的類型Detail 來簡化表示,即元素Weather Detail Information(vp4).在主界面的上方,存在一條工具欄,它在實現中作為Activity 的特殊附屬控件ToolBar 或ActionBar 而存在,因此在擴展后的IFML 中,我們將它以工具欄元素ToolBar(vc3)嵌套在WeatherMain Screen 元素內,來表示它的附屬關系.而在該工具欄上,存在各式的按鈕、文本以及圖標,它們在開發中作為Button、Text 以及ImageButton 等類型的控件而出現.在IFML 中則對應于本文擴展的按鈕Home Button(vp1)、文本Title(vp2)和圖標LocatingIcon 元素(vp3)(這里,為了簡化只顯示了其中的定位圖標).隨后,圖1-2 中應用的側邊欄,在開發中以DrawerLayout 這一布局來實現,并且通常為整個應用的所有Activity 所共享,為此,我們在IFML 模型中以抽屜元素SideBar 來表示(vc2),并獨立于所有其他的視圖容器類元素.其上也包含這一側邊欄中的各類文本組件(vp5,vp6,vp7).同時,在主界面和側邊欄可通過左右滑動來相互切換,因此可使用擴展后的滑動事件,即圖中的right swipe 和left swipe 元素以及它們所引出的交互流(e2,i2和e5,i5)來表示,在開發中,它們通常對應于滑動類型的事件監聽器.在工具欄上的Home 按鈕以及定位圖標上的點擊事件也類似于此(e1,i1和e3,i3).
可以看到,文中對視圖容器、視圖組件以及事件的擴展可幫助開發者有效地區分各個不同類型的界面、控件以及事件.同時,這些IFML 元素也能與各類開發組件相對應,因此能夠有效地指導開發工作系統地進行.

Fig.7 A part of IFML model for Good Weather after the Android extension圖7 擴展后Good Weather 應用的部分IFML 模型
此外,該應用中與事件交互相關的邏輯我們也可使用參數、表達式以及行為來表示.在該應用中,用戶需要先進行定位(元素vp3上的觸摸事件e3),隨后應用根據地點位置請求天氣信息數據(我們將這個請求過程用行為元素Locating 來表示,即a1),并最終將這一數據在組件Weather Detail Information 中顯示出來.這一串邏輯的具體內容也需要參數和表達式的幫助:我們用參數isLocated(p1)來表示該應用是否進行了定位操作并獲取了天氣信息,同時,該參數使用圖中默認表達式(xd1)將其初始化為false,即最初并未進行定位.根據設計意圖,僅當進行了定位,即參數isLocated 為true 時,才會顯示詳細的天氣信息,即組件Weather Detail Information 的顯示.因此,我們將激活表達式(xa1)的內容設置為 if(isLocated){return true;}else{return false;},使其計算結果與參數isLocated 保持一致,并由組件Weather Detail Information 持有該激活表達式.顯然,其顯示狀態最終與參數isLocated 保持一致,從而達到了我們的設計要求.對應地,Locating 行為具體的邏輯執行可以由這一執行表達式(xe1)表示:我們以isLocated=true 輕量地表示參數isLocated 所代表的定位,發送請求,信息展示這一連串邏輯的執行,并且執行完成后isLocated 的值發生了改變,因此也將最終決定組件Weather Detail Information 顯示與否.
通過執行表達式的使用,我們將應用的內部邏輯以表達式的形式進行輕量級的建模,一定程度上避免了使用UML 動態模型進行詳細的行為建模的繁瑣過程,同時將IFML 中的邏輯表示僅限于IFML 本身,避免了多模型相互引用的情形,最終降低了建模的復雜度,簡化了建模過程.
本文的安卓端擴展,實際上在IFML 模型的泛用性(抽象能力)以及表現力上達到了一個均衡點.利用該擴展后的IFML 為安卓應用進行建模時更加方便、快捷,在降低建模的復雜度的同時也使得模型所展現的設計意圖更加精準、明確.同時,通過將安卓端常用元素加入擴展中,使得建立的IFML 模型也更加貼近實際的安卓應用.在開發過程中,它能夠作為設計標準指導實現工作的進行,避免實現工作偏離設計意圖所導致的額外工程量,因此,能夠有效地提高開發效率.此外,基于該擴展后的IFML 模型,也可實現部分開發工作的自動化.典型的方式,例如利用這一建立/修改后的IFML 模型,自動化生成實現代碼,或是生成相應的測試用例,驅動應用的開發/演進工作的進行,并最終利用這些用例檢驗應用開發是否正確,都能極大地提高安卓應用的開發效率.為此,本文也研究了對擴展后的IFML 模型的形式化定義,使得通過IFML 模型自動化生成測試用例或是實現代碼,都成為可能.
IFML 標準文檔僅對模型的語法進行了形式化的定義,而其中的語義則采用了自然語言這一類非形式化的方式進行了描述,因此,標準中的許多語義不夠準確.為了更好地支持IFML 模型在安卓應用開發中的使用,我們對標準中模糊的部分進行了嚴格的定義,并連同前文提出的安卓端擴展,對擴展后的IFML 模型進行了形式化的定義.更重要的,本文也對IFML 模型的動態語義進行了形式化定義,從而使得IFML 模型中事件觸發、交互流傳遞以及模型狀態遷移都有唯一的解釋.因此,在使用該IFML 模型中的定義來描述安卓應用中的界面構成,以及界面間的交互時都極為準確,避免了該IFML 模型在作為設計意圖體現時可能產生的歧義.
首先,我們給出IFML 模型中各個重要元素的形式化定義.
定義1.X={x1,x2,…,xn}為IFML 模型中被使用到的表達式集合.對于任意x∈X,x為一個三元組x=(xt,l,b),其中,xt用于標記該表達式所屬的具體類型;l表示解析當前表達式所使用的語言,如Java、OCL 等;b以文本形式存儲了該表達式的表示.本文將X按照不同的類型劃分為不同的集合,由第3.2 節已知,共有4 個子類型,即X=XA∪XI∪XD∪XE,XA,XI,XD,XE分別表示為激活表達式、交互流表達式、默認表達式以及執行表達式的集合.
定義2.VE={ve1,ve2,…,ven}為IFML 模型中視圖元素的集合.VE可進一步分為視圖容器和視圖組件,記為VE=VCT∪VCP,其中,VCT表示視圖容器的集合,VCP表示視圖組件的集合.無論對于視圖容器還是視圖組件,對任意ve∈VE,均有ve=(vet,ax,SE,vc),vet標記了該視圖元素的具體類型;ax∈XA為該元素對應的激活表達式;SE表示其上可以觸發的視圖元素事件的集合(見定義5);vc∈VCT,表示該容器/組件的父容器.ax與SE均可為空,當ax為空時,該視圖容器/組件默認激活.僅當ve∈VCT時,vc可能為空,表示該視圖容器為最外層容器.
定義3.VP={vp1,vp2,…,vpn}為IFML 模型中的視圖組件部件的集合.對于任意vp∈VP,均有vp=(vpt,ax,SE,pvp),vpt表示該視圖組件部件的具體類型;ax表示該視圖組件部分所對應的激活表達式,SE表示其上可以觸發的視圖元素事件的集合,pvp∈VCP∪VP,表示該組件部分所屬的父視圖組件或父視圖組件部件.ax,SE,pvp均可為空,特別地,當ae為空時,表示該視圖組件部件默認活躍.
定義4.A={a1,a2,…,an}為IFML 模型中行為的集合.對于任意a∈A,均有a=(at,ax,SE,vc,ex),at表示該行為的具體類型;ax為該行為所對應的激活表達式;SE表示從屬于該行為的行為事件的集合;vc表示為該行為所從屬于的視圖容器,即父容器,其值可以為空,表示該行為獨立于所有的視圖容器;ex∈XE,即本文擴展的execution Content,用于表示其內部邏輯對應的執行表達式.
定義5.E={e1,e2,…,en}為IFML 模型中事件的集合.對于任意e∈E,均有e=(et,ax,ix,SI,pe),其中,et表示為該事件的具體類型;ax代表該事件對應的激活表達式;ix∈XI為交互流表達式,其計算值表示該事件在當前情況下會觸發哪些交互流;SI表示為該事件可觸發的交互流的集合;pe表示為該事件所從屬的視圖容器/視圖組件/視圖組件部件/行為.其中,ax,ix,pe均可為空.當ax為空時,表示該事件默認活躍,當ix為空時,會觸發SI中所有交互流.本文按照擴展內容,將事件E分為3 個類型,記為E=ES∪EA∪EV,其分別表示為系統事件、行為事件以及視圖元素事件的集合.當某一事件屬于視圖元素事件時,其pe為視圖容器/視圖組件/視圖組件部件;當它為行為事件時,pe恒為行為,即若ae=(et,ax,ix,SI,pe)∈EA,則有pe∈A.
定義6.I={i1,i2,…,in}為IFML 模型中交互流的集合.交互流可分為導向流與數據流,記為I=N∪D,對于任一i∈I,均有i=(it,s,t,PBG).其中,it表示該交互流具體為導向流還是數據流;s為觸發當前交互流的事件,表示為該交互流的起始點;t為該交互流的終點,t∈VE∪VP∪A,為視圖元素、視圖組件部件或行為.特別地,一個行為事件觸發的交互流不再導向另一個行為,即任意的行為事件ae=(et,ax,ix,SI,pe),若有交互流i=(it,s,t,PBG)使得i∈SI,則t?A.PBG={pb1,pb2,…,pbn}為參數綁定組,表示該交互流所攜帶的數據綁定信息的集合.對于任意pb∈PB,其表示為一條參數綁定信息,有pb=(sp,tp),表示為在當前狀態下將源參數sp的值傳遞給目標參數tp.
定義7.P表示為IFML 模型中被使用到的參數的集合,有P={p1,p2,…,pn},對于任意p∈P,其可用一個三元組表示p=(d,te,dx):d以枚舉類型表示該參數p為入參或是出參;te表示該參數的具體類型;dx∈XD,以默認表達式的形式給定該參數在初始情況下的默認數值.
有了以上定義,我們可以給出IFML 模型的形式化定義.
定義8.一個IFML 模型為一個六元組M=(V,A,E,I,X,P,vI),其中,
·V={v1,v2,…,vn}為視圖元素(視圖容器和視圖組件)和視圖組件部件的集合,即V=VE∪VP.
·A={a1,a2,…,an}為行為的集合.
·E={e1,e2,…,en}為事件的集合.
·I={i1,i2,…,in}為交互流的集合.
·X={x1,x2,…,xn}為表達式的集合.
·P={p1,p2,…,pn}為參數的集合.
·vI∈V為該IFML 模型最初情況下顯示的視圖容器.
在給出擴展后IFML 模型的語法后,本文也給出該IFML 模型的動態語義,即對IFML 模型的模型狀態和模型中的執行路徑進行定義.IFML 模型雖然與常用的控制流模型類似,使用交互流來表示狀態的轉化,但是由于其復雜性,控制流模型中簡單的“點-邊-點”模式難以表現出IFML 模型中交互執行的豐富含義.同時,根據IFML的語義,是事件觸發了交互流從而導致了狀態的轉化,交互流無法脫離事件而單獨存在,故本文以IFML 模型中的事件和狀態的交替序列來表示其執行路徑.IFML 模型的運行時狀態,可記為CS,表示一組激活的視圖容器、視圖組件、視圖組件部件和行為的集合,以及參數和它們當前值的映射集合.形式化地,狀態CS可定義為一個二元組(CM,CA),CM為上述的激活元素集合,即CM?V∪A;CA即為上述的參數和它們當前值的鍵值映射集合P→U,其中,P,U分別是參數以及實際值的集合,對于任意參數pi∈P,均有唯一實際值ui∈U與之對應.
為了更好地描述狀態CS=(CM,CA),我們又有以下函數的定義.
·定義函數計算激活表達式來判斷元素是否被激活:對于任意元素vi∈A∪V∪E,其激活表達式ax有函數eval(vi.ax,CA)=b來計算在CA所給定的參數值下該激活表達式的值,b為布爾值類型,為true 時,表示該元素vi被激活.
·定義函數來判斷在給定可見元素時其他元素是否可見:對于任意元素vi,vj∈V∪A,存在函數Lv(vi,vj)=b,b為布爾值類型,為真時,表示在元素vi可見時vj也可見.當給定擁有當前狀態的視圖焦點的可見元素vi∈V時,該元素必定已被激活,即對于vi的激活表達式axi有eval(axi,CA)=true.此時,vi的父容器也必然可見,即對于vi的父容器pvi,有Lv(vi,pvi)=true 成立.據此定義,該Lv函數可繼續遞歸于pvi的父節點.特別地,當可見元素vi∈A時,有且僅有vi自身可見,即僅有Lv(vi,vi)=true.從而我們可以通過該函數獲取視圖焦點轉移后可見元素的集合,即若vi獲得視圖焦點(當前可見),則當前所有的默認可見元素可用集合{x∈A∪V|Lv(vi,x)=true}來表示.
·定義函數來執行行為中的執行表達式:對于任意元素ai=(at,ax,SE,vc,ex)∈A,有函數exec(ex,CA)=CA′,表示為通過執行ai中的執行表達式來改變CA中元素的數值,從而得到新的映射集合CA′來代替CA.
·定義函數來計算事件中的交互流表達式獲取觸發的交互流集合:對于任意事件ei=(et,ax,ix,SI,pe)∈E,其下的交互流表達式ix∈XI,存在函數eval(ix,CA)=SI′,SI′表示為ix所對應的事件在當前狀態下所觸發的交互流的集合,并有當ix為空時,eval(ix,CA)=SI.
·定義函數來執行交互流中的參數綁定信息:對于任意交互流ii=(it,s,t,PBG),若其PBG存在,則有函數exec(PBG,CA)=CA′表示執行這一值的傳遞過程,形成新的參數與其值的映射集合CA′代替CA表示狀態參數的更新.
·定義函數計算默認表達式初始化參數的值:對于任意參數pi=(d,te,dx)∈P,有函數exec(dx,CA)=CA′表示對該參數的數值進行初始化,CA′中參數pi被賦予了其dx中給定的數值.并在初始狀態下,給定CA=?,可對于IFML模型中所有的參數pi∈P,執行CA←exec(dx,CA),最終即可得到其初始的參數與其值的映射集合.
在當前狀態CS=(CM,CA)下,我們又可以定義函數enable:CM→E,enable(CM)表示為當前狀態下活躍元素可觸發的事件集合,并對于其中任意e=(et,ax,ix,SI,pe)∈enable(CM),均需滿足eval(ax,CA)=true,pe∈CM.通過從enable(CM)中選擇任意事件ei=(ete,axe,ixe,SIe,pee)后,我們可以通過以下步驟從原狀態CS變化到新狀態CS′,即
1.若pee∈A,則需要先執行該行為,記為a=(ata,axa,SEa,vcta,exa),其中的執行表達式,即CAi'←exec(exa,CAi).
2.取SI′=eval(ixe,CAi'),由上述定義可知集合SI′表示為該ei在當前狀態下所觸發的交互流集合,并且其中的導向流集合可記為SNI,SNI?SI′.對于交互流i=(iti,si,ti,PBGi)∈SI′,需要依次執行CA′←exec(PBGi,CAi'),即進行參數的傳遞.
3.根據第2 步中導向流集合可重新計算新狀態CS′的CM′:先將CM刪除其中視圖焦點轉移過程中失去視圖焦點的部分,即.隨后,添加其獲得視圖焦點的元素,即遍歷選擇SNI中的導向流ii=(iti,si,ti,PBGi)∈SNI,可知下一狀態下獲得視圖焦點/直接控制流的元素記為ti,對其逐個進行.最終完成遍歷后即可獲得新狀態CS′下對應的CM′.
最終我們可給出下述定義9.
定義9.對于任意給定的IFML 模型M=(V,A,E,I,X,P,vI),根據M生成的一條n步長(n>0)的可執行路徑ρ定義為以下一條序列:

其中,CSi(0≤i≤n)即為上述定義的在該可執行路徑ρ中的一個運行時狀態.特別地,CS0表示為該IFML 模型的初始狀態,記為CS0=(CM0,CA0).為初始化CA0,可先給定CA=?,對該IFML 模型中所有的參數p=(d,te,dx)∈P,逐次執行CA←exec(dx,CA),最終即可得到其初始的映射集合CA0.而已知vI表示為該IFML 模型的初始視圖容器,則有CM0={x∈A∪V|Lv(vI,x)=true&&eval(x.ax,CA0)=true},可以獲得最初的CM0.
不妨仍然以圖 7 所示的 IFML 模型為例.由第 3.4 節中的建模過程可知,對于該 IFML 模型M,有M=(V,A,E,I,X,P,vI),其中有V={vc1~vc3,vp1~vp7},A={a1},E={e1~e5},I={i1~i5},X={xe1,xa1,xd1},P={p1},且有初始視圖容器vI=vc1,即為圖1-1 所示的主界面(即WeatherMainScreen 元素,其最左端標有D 字樣,含義為Default,表示該最外層的視圖容器即為初始容器).此時,初始狀態CS0=(CM0,CA0).最初CA0=?,對于模型中的唯一參數p1=(d1,te1,xd1),對其初始化,有CA0←exec(xd1,CA0),CA0={p1→false}為初始的CA.并且,已知當且僅當vx∈{vc1,vc2,vp1,vp2,vp3,vp4},有Lv(vc1,vx)=true(表示當vc1顯示時,這些元素也默認顯示).而其中vp4=(vc1,xa1,?,null),其顯示狀態受激活表達式xa1影響,在初始狀態CA0下eval(xa1,CA0)=false,即不顯示.故,CM0={x∈A∪V|Lv(ti,x)=true&&eval(x.ax,CA0)=true},即CM0={vc1,vc2,vp1,vp2,vp3}.至此,初始狀態CS0=(CM0,CA0)的初始化完成.
隨后,通過函數enable(CM0)={e1,e2,e3}可獲得當前可觸發的事件.不妨假設此時執行事件為e3,記為e3=(et3,null,null,SI3,vp3).有SI3={i3},有且僅有1 條交互流,即為e3唯一能觸發的交互流,其中,i3=(it3,e3,a1,?),可知視圖焦點轉移到行為a1上,a1=(at1,null,SE1,null,xe1).此時,既無參數傳遞,也無執行表達式,故CA不變,有CA1=CA0={p1→false}.同時,CM首先去除失去焦點的元素,即觸發事件e3的父元素CM0},有隨后,CM再加上重新獲得視圖焦點的元素,即a1.而a1∈A,由之前的函數定義可知,有且僅有Lv(a1,a1)=true,且a1未持有激活表達式,故{a1}.通過執行事件e3,我們實現了狀態轉移:

而在狀態CS1下時,enable(CM1)={e4},e4=(et4,null,null,SI4,a1).此時,需執行a1中的執行表達式xe1,因此有CA2←exec(xe1,CA1),最終CA2={p1→true}.同時,SI4={i4}僅有1 條交互流,i4=(it4,e4,vc1,?)即為所需執行的交互流,其目標元素vc1將獲得視圖焦點.在去除失去焦點的元素a1后,CM2'=?.已知當且僅當vx∈{vc1,vc2,vp1,vp2,vp3,vp4},有Lv(vc1,vx)=true,而且CA2={p1→true},eval(xa1,CA2)=true,故與初始狀態CS0不同,元素vp4也將加以顯示,即,最終,CM2={vc1,vc2,vp1,vp2,vp3,vp4},故我們實現了第2步狀態轉移
從IFML 模型的初始狀態CS0=(CM0,CA0)開始,按照上述示例不斷地通過enable 函數選擇一個當前可觸發事件執行并更新狀態,我們便可獲得一條可執行路徑

通過對擴展后的IFML 模型中各元素的屬性以及各元素間關系的形式化定義,在將這些元素轉化為安卓應用中的組件元素,即代碼的生成時,能夠形成固定的轉化規則,使得自動化代碼生成成為可能;而對IFML 模型中模型狀態以及可執行路徑的定義,則制定了IFML 模型狀態間通過觸發事件來互相轉化的轉化規則,從而使得自動化地遍歷IFML 模型生成測試用例并執行成為可能,本文也對這一部分內容加以實現,可詳見下一節.
經過本文上述章節對IFML 進行的安卓端擴展,在安卓應用開發中使用該擴展后的IFML 進行對應用需求、設計的建模,能夠使得應用的設計以更精確、更加貼合實際安卓應用的方式來加以展現.并且,通過文本對該擴展后的IFML 模型的形式化定義,這一IFML 模型除了在設計和實現上起到這一指導性的作用外,還能具有諸如自動化測試之類的具體用途.基于該IFML 模型的測試能夠檢測應用的實現是否與應用的設計保持一致,從而保證應用在開發過程中的正確性,這是設計模型的一種常見使用場景.本節將探索擴展的IFML 在安卓應用基于模型的測試這一場景下的可行性.為此,本文首先實現了基于擴展的IFML 模型的建模與測試工具ADAMANT,并選取了5 個當前較為知名的開源安卓應用作為案例來進行分析研究.
工具ADAMANT 源自于IFML 官網上一個基于Sirius 項目[8]的IFML 建模項目.我們對該項目按本文面向安卓應用的IFML 擴展進行了修改和完善.最終,ADAMANT 以eclipse 插件的形式集成起來,使用它即可在eclipse IDE 上以圖形化的方式為安卓應用進行IFML 建模.如圖8 所示,即為我們提供的IFML 建模視角.

Fig.8 The modeling perspective of ADAMANT圖8 工具ADAMANT 的建模視角
在如圖8 所示的視角中,用戶在建立相應的IFML 模型項目后,可以從右側工具欄內選擇不同的包,從中選擇不同類型的IFML 元素,將其拖拽至主界面,這即表示在該IFML 模型中建立了相應的元素實例;在選中IFML模型中的元素實例后,也可以在下方的屬性標簽欄中對該元素的屬性進行設置.此外,右側工具欄中,Android、AndroidExtensions 等即為本文對該工具的安卓端擴展,利用這些包內元素,可以簡化建模過程,使用者也可以創建具有安卓特點的元素實例,使得建立的IFML 模型更加貼合安卓應用.
隨后,我們也為ADAMANT 添加了測試功能——當使用者根據該IFML 模型中的設計實現了相應的安卓應用后,ADAMANT 可以根據這一IFML 模型自動化地生成相應的測試用例,并在給定的設備上自動化地執行,從而檢驗最終實現的應用制品是否與原本的應用設計保持一致.具體而言,ADAMANT 讀出了IFML 模型數據后,根據第4 節中對IFML 模型以及其中可執行路徑的定義,ADAMANT 通過模型遍歷的方式,生成大量的可執行路徑,并可按不同的事件覆蓋準則選擇路徑集合將其轉化為測試用例并執行.
這個過程中,最為重要的即為模型遍歷,圖9 給出了該遍歷算法的偽代碼表示.算法主體,即pathsTraversing函數的入參CS 表示為當前模型的狀態,Paths 表示為生成測試用例的集合,SE 則表示為當前路徑中事件的集合.模型的遍歷以初始狀態CS0開始執行這一pathsTraversing 函數,Paths 和SE 均為?.在該函數中,它通過enable函數獲取當前狀態下任何可能觸發的事件,遍歷選擇事件加入當前的路徑的事件集合SE 中(第2 行~第4 行).若達到中止條件時(第5 行,中止條件諸如當前路徑中的事件數達到了預先設定的最大值),則檢查當前事件是否未被覆蓋并對該路徑真正可執行進行檢測(第6 行).如果可行,便會根據當前的可執行路徑生成對應測試用例并將其加入Paths 中(第7 行~第9 行);而若未達到中止條件,則通過possibleSIGroup 函數獲取該事件可能觸發的交互流(第10 行~第11 行),并根據選擇的交互流更新模型狀態為CS′,遞歸上述pathsTraversing 函數(第12 行~第13 行).此過程中獲得的Paths 集合即為根據該IFML 模型生成的測試用例集合.最后,ADAMANT 在測試框架Robotium[25]的支持下,將這些測試用例運行在待測應用之上,并記錄測試執行時間、測試錯誤日志等測試執行信息.

Fig.9 The algorithm of generating test cases via traversing the IFML model圖9 遍歷IFML 模型生成測試用例算法
在實際應用中,ADAMANT 允許開發人員將應用設計意圖以IFML 模型的形式來展示,從而指導應用的開發工作,使開發人員達成統一的設計認知,避免誤解.同時,ADAMANT 根據IFML 模型生成的測試用例,可作為應用實現和設計是否保持一致的一個檢驗標準,當測試用例執行失敗時,則說明當前的應用很可能與設計意圖相悖,并且ADAMANT 記錄的錯誤日志也可幫助開發人員定位異常點.在應用的演進過程中,ADAMANT 的效果則會更加明顯:開發人員根據新的需求使用ADAMANT 對IFML 模型進行修改,以指導應用的修改工作,而ADAMANT 高度自動化的測試功能,則避免了在不斷演進過程中測試用例的重復編寫,提高了開發效率.
由于應用的開發工作是一個較為漫長的過程,本文沒有在設計時就開始利用ADAMANT 進行建模,隨后實現應用并使用ADAMANT 的測試功能檢驗開發工作的正確完成.替代性地,本文直接選擇了當前已開發好的5個知名的應用.這5 個應用均來自Wiki 和Github 所提供的安卓知名開源應用的列表[9,10].我們選定了這些應用最新發布的版本,作為本文的實驗版本.并且,根據對這些應用的使用體驗、核心源代碼理解等獲取的信息,我們使用ADAMANT 對這些應用逆向地進行了手工IFML 建模.最終,應用ADAMANT 的測試功能,基于這些IFML模型,對應用進行了相應的測試.表2 展示了這些應用的基本信息以及IFML 模型信息.

Table 2 The informations of these 5 five apps and their IFML models表2 5 個應用的基本信息以及IFML 模型信息
表2 中展示了這5 個應用的版本、類型、代碼行數以及應用代碼中Activity 的數量(Activity 為安卓應用中最重要的應用組件,一個Activity 粗略地代表應用的一個主界面).受文章篇幅所限,文本在此無法給出這些應用的IFML 模型的全部信息,在表中僅給出了這些IFML 模型中各類重要IFML 模型元素,即視圖容器、視圖組件、事件、交互流以及表達式的數量.此外,表中也給出了建立這些IFML 模型所花費的時間.
總體而言,Activity 數量以及代碼行數體現了這些應用的規模,而我們建立的IFML 模型的規模也與應用基本保持一致.雖然建立這些IFML 模型花費了4~20 小時不等,但考慮到我們所選擇的均是當前具有較長發展歷史、具有一定規模的成熟應用,相較于它們數月的開發時間來說,花費20 小時以內從頭建立這些IFML 模型的代價是可以接受的.并且,這些成本僅為初次成本,隨著應用的不斷演進,開發人員僅需要低額的工作量便可在已有IFML 模型上進行修改,因此,整體的建模成本將會被不斷稀釋.然而,該IFML 模型在開發中的指導作用可有效地分解開發復雜度,促使開發工作高效、系統地進行.并且,基于該IFML 模型進行的測試能夠有效地提高測試效果,并且避免了在應用開發迭代中編寫測試用例的重復勞作.此外,該IFML 模型也擁有廣泛的應用前景,伴隨著自動化程度的提高,基于該IFML 模型的諸如自動化代碼生成的研究也將被推進,因此,可進一步解放人工勞力,提高開發效率.據此,我們認為建立IFML 模型所花費的時間是值得的.
為了說明IFML 模型在驅動安卓應用開發中,除了提供設計和實現上的指導性作用外的廣泛用途,我們還探索了基于IFML 模型對安卓應用進行自動化測試這一方法的可行性.通過上述實驗為這5 個應用進行了IFML 建模之后,本文還通過ADAMANT 依據建立的IFML 模型對這些應用進行了測試.使用安卓模擬器作為我們的測試設備,在測試中將模擬器設備分別設置為Nexus5X、Nexus S 以及Pixel,將模擬器的安卓版本分別設置為4.4、5.0 以及5.1,進行了實驗.最終,這些實驗結果雖然存在一些輕微的差異,但均可正常進行測試,這表明,利用ADAMANT,同一個IFML 模型可廣泛應用于不同的安卓設備以及安卓版本.
為了量化測試效果,本文還詳細列出了設備設置為Nexus5X,安卓版本設置為5.1 的模擬器下ADAMANT的具體測試結果,見表3.ADAMANT 運行在8G 內存、i7 處理器的Win 10 筆記本電腦之上,最終測試實驗結果見表3.同時,為了對比測試效果,我們將ADAMANT 進行測試所花費的時間記錄下來(表中“執行時間”欄),在相同的應用上使用安卓最主流、最廣泛使用的隨機事件流工具Monkey 進行實驗,并給定了相同的執行時間.
表3 第2 欄表明了該應用對應的IFML 模型的事件數,由于在測試中是通過模型遍歷,以事件覆蓋為準則生成測試用例,因此,IFML 模型規模越大,事件數越多,ADAMANT 生成的測試用例也越多,執行時間也越長.隨后,其3~5 欄表明使用的測試方法、該方法生成的測試用例數量以及這些用例中總共執行的測試操作或事件數量.第6 欄~第9 欄則表明了用例執行的結果——包含這些用例中執行失敗的數量、這些用例執行所達到的代碼行的覆蓋率、執行的時間以及在該測試進行中發現的缺陷或異常.

Table 3 Testing result of test cases for these 5 apps表3 對5 個應用的各項測試執行結果
從靜態代碼覆蓋率來看,ADAMANT 在這5 個應用上均達到了50%以上的代碼覆蓋率,且其均值達到了68.18%,相較于Monkey 的均值49.44%,有將近18.74%的代碼覆蓋率的提升.這一巨大的提升,主要體現在以下3個方面:(1)通過ADAMANT 所建立的IFML 模型具有豐富的語義,且在經過擴展后可以以表達式的形式來表示各事件執行、元素顯示、頁面跳轉之間的關系,因此,能夠生成高度關聯性的測試用例.而Monkey 這類隨機測試由于其隨機性,將會出現大量的冗余以及無效事件,因此拉開了測試差距;(2)由于該IFML 模型是手工建立的,因此在該IFML 模型中,使用者能為特定的輸入控件提供候選輸入內容,有效的文本輸入大大提升了測試用例的效果;(3)通過本文的擴展,IFML 模型可以建立種類豐富的事件,用戶操作如長按、雙擊、滑動、縮捏等,系統事件如Wifi 連接、數據連接等,而這一點在Monkey 上有較大的欠缺,例如它只能支持簡單的點擊以及滑動這兩種用戶操作.
隨后,在測試用例執行上,存在一定量的執行失敗測試用例,我們將其展示在表3 第6 欄中.對這些失敗的用例進行了人工檢查,其中,大多數源自于應用本身的缺陷,或是應用本身的設計與建模者的認識相悖,其中便存在著應用實際的開發與初始的設計不一致的情形.此外,執行失敗也與外部環境存在一定關聯.例如,在OwnCloud 中,由于網絡波動或是服務器異常,部分操作可能會超時,最終導致測試用例執行失敗.
最后,在缺陷發現上,ADAMANT 發現了6 個缺陷,見表4.而Monkey 只發現了第5 條.其中,第1、2、4、5條缺陷均引發了應用的崩潰;第3 條和第6 條缺陷未引發應用崩潰,但ADAMANT 檢測到了OwnCloud 和Omni-Notes 應用的IFML 模型與實現的不一致性.我們通過對比Github 上相關的缺陷issue,發現這兩個缺陷均由開發者確認為實現中的真實錯誤和疏漏.

Table 4 Details of defects found in these 5 apps表4 5 個應用中發現的缺陷信息
綜合來看,ADAMANT 所實現的測試功能,可在較短時間內對應用進行有效的測試,達到較高的測試覆蓋率,并發現應用中的缺陷,以及在應用中與原本設計存在偏差的部分.因此,鑒于ADAMANT 良好的測試效果,當開發人員通過ADAMANT 建立IFML 模型作為應用的設計時,其測試功能可以幫助開發人員檢驗實現完成的應用是否與原設計意圖保持一致,以盡可能地減少實現中的偏差所帶來的額外工作量.另外,ADAMANT 也可支持增量式的開發過程:在應用演進中,開發者可以逐步建立并不斷豐富IFML 模型,此時,ADAMANT 依然可以進行相應的測試,從而指導開發的進行,并且伴隨著IFML 模型的不斷精化,其生成的測試用例也會更加精確、有效.這一過程中,出眾的測試效果以及極低的測試成本能夠抵消IFML 的建模成本,最終極大地提高開發效率與質量.
近年來,考慮到目前的移動系統和設備的繁多,為了降低重復開發的成本,將模型應用于移動應用開發的研究大量涌現[11].Parada 等人[4]直接基于UML 類圖和時序圖提供移動應用的高層抽象模型并實現了自動化生成;Balagtas-Fernandez 等人[12]設計了Mobia 這一圖像化的移動應用建模套件進行移動應用的模型驅動開發;也有專門針對數據驅動的應用,基于md2這一MVC 結構模型進行移動端跨平臺模型驅動開發的研究[5].近年來,也有不少將圖形化領域特定語言(DSL)應用于移動應用建模的研究,Vaquero-Melchor 等人[13]對復數DSL 進行擴展,用于對應用的各個方面的信息,如外部交互、移動性以及上下文環境等進行建模,并整合為一個active DSL.Rieger 等人[14]提出了Münster App Modeling Language(MAML),一種面向非技術人員的圖形化DSL,該語言以流程的方式描述了數據、視圖、業務邏輯以及用戶交互.但MAML 僅以關鍵的字詞代替了流程中視圖的具體展示和事件交互,因此,在表現移動應用豐富GUI 時表現能力不足.此外,Vaupel 等人[15,16]通過在模型上增加其抽象層次,從而提供了一種可詳可略的建模方式,使得移動應用開發更加靈活多變.國內,杜一等人[17]提出了基于E-UIDL 模型的移動應用開發方法,該模型著重于應用界面,并以領域模型、抽象用戶界面模型等等諸多子模型來對界面進行描述,提高其可復用性及可擴展性,但很顯然,這也引起了模型在可用性上的不足.對于本文所用到的IFML 標準,也有類似的研究.Brambilla 等人[18]通過建立移動應用的IFML 模型,來生成對應的HTML5、CSS3 等網頁代碼,最終包裝在移動端安卓與iOS 平臺的應用中,并在實際的開發案例中進行實驗.然而,該研究仍然需要一定的人工參與,且將網頁代碼作為中轉產物將會遺失移動平臺獨有的信息.而本文對IFML 進行了安卓端擴展,使得IFML 用于安卓應用建模時擁有較高的匹配度,雖未進行具體的代碼自動化生成工作,但本文還對擴展后的IFML 模型進行了形式化定義,這為代碼自動化生成打下了基礎.而在這一定義下,文本實現的基于該IFML 模型的自動化測試方法,也能作為判斷設計與實現一致性的手段,以驅動開發、演進工作的進行.
現有研究工作中,IFML 被廣泛應用于眾多領域之中進行建模以及相應擴展的研究.例如,Ed-Douibi 等人[19]利用IFML 建立網頁模型,生成符合REST 原則的網絡應用編程接口;Raneburger 等人在文獻[20]中描述了使用IFML 實現獨立多設備 GUI 生成的機制,并將其與 Model Based Useware-Engineering(MBUE)和 Unified Communica-tion Platform(UCP)進行了簡單的比較;Frajták 等人[21,22]利用IFML 對一般應用建模并轉化為對應的前端測試模型,并最終利用該模型進行了針對前端的自動化測試用例的生成;Brajnik 等人[23]通過對一般應用進行IFML 的建模,提出了將應用模型中的數據流和控制流進行分離的可能性;Laaz 等人[24]則嘗試將IFML 模型與OWL (Web ontology language)實體整合起來,以增強網頁應用的用戶接口的展示.這些基于IFML 模型探索代碼生成與測試執行自動化的研究,證明了將IFML 應用于軟件開發自動化的可行性和有效性.此外,Huang 等人[25]提供了從安卓應用中抽取IFML 模型的方法,該方法也可與本文的工作相結合,以降低從已有開發項目中建立IFML 模型的成本.
目前,針對安卓應用的自動化測試工具,在工業界,諸如Robotium[26]、Appium[27]以及MonkeyRunner[28]之類的自動化測試執行工具已經較為普及.近年來,學術界大量的研究著眼于利用模型來自動化生成測試用例,著名的有,2012 年Amalfitano 等人基于GUIRipper[29]進行安卓端擴展的研究工作AndroidRipper[30].它以動態執行的方式遍歷安卓應用,并生成相應的GUI 模型,最終實現測試的目的.從此之后,這類自動化構建模型生成測試輸入的測試方法逐漸成為學術界安卓測試的主流之一:Azim 等人[31]通過綜合使用靜態分析和動態執行的方式,生成安卓應用對應的動態和靜態活動轉移圖(activity transition graph),從而進行針對性的以及廣度優先的應用系統化遍歷測試;Choi 等人[32]結合機器學習技術來構建模型,并在學習中以頁面跳轉來實現狀態變更,從而減少了應用的重啟;2015 年,AndroidRipper 的后續版本MobiGUITAR[33]誕生,它用一個狀態機模型代替原來無狀態的GUI 模型,并且在模型遍歷、更新算法上進行了優化;Su 等人[34]采用逆向工程靜態分析和動態UI 探測來抽取安卓應用的隨機模型,然后基于模型生成測試用例加以執行,使用Gibbs 抽樣來分析執行結果,并以此提煉原隨機模型,進一步生成更加有效的測試用例.近年來,不少基于程序分析、隨機測試、組合測試等等的測試方法也引起了學術界的關注.Mirzaei 等人[35]提出了通過程序分析技術獲取對輸入的各種約束,從而削減測試輸入組合的方法,Song 等人[36]提出了通過直接調用事件處理器的回調函數而非基于 GUI 事件的隨機測試方法,Sadeghi 等人[37]則將安卓權限引入測試之中,并通過混合式的程序分析方法來減少不必要的權限組合測試.上述這些方法通常獨立于應用的開發工作,而本文基于IFML 模型進行測試,是作為將IFML 應用于安卓應用設計建模,并指導應用開發工作的一環.本文的方法立足于IFML 模型的這一前提,因為IFML 模型的存在,其測試效果更佳,也能發現應用設計和實現不一致的地方,從而提高了將IFML 模型引入安卓應用開發的功效.
在移動平臺,尤其是安卓平臺飛速發展的今天,為滿足廣大用戶紛繁復雜的對移動的需求,安卓應用的復雜度逐級攀升.而安卓設備和系統存在的多樣化和碎片化,使得在安卓應用開發中增加了額外開發的工作量和難度.針對這一現象,本文根據安卓應用事件驅動的特性,將IFML 模型引入安卓應用的開發過程,希望開發者能將應用的設計以IFML 模型的形式進行具象化,降低開發難度,指導應用的開發工作.然而,目前寬泛的IFML 并不適用于移動/安卓應用建模,為此,本文對IFML 標準進行了面向安卓端的擴展,對擴展后的IFML 模型進行了形式化定義,使得無論是基于IFML 模型生成代碼還是執行測試等等方法都成為可能.最后,本文實現了相應的建模與測試工具ADAMANT,使用它為5 個應用建立了IFML 模型,并基于這些IFML 模型進行了自動化測試.其良好的實驗結果顯示了本文對IFML 進行的安卓端擴展、對IFML 模型進行的形式化定義的有效性,以及將其應用于軟件開發過程中的可行性.
當前,該方法處于初步建立的階段,其應用于真實的安卓軟件開發中的有效性還有待檢測.因此,在未來的研究中,我們將在實際的應用開發案例中,將完全人工開發的方式以及基于該擴展后的IFML 模型的開發方式,乃至于其他模型驅動開發方法進行對比實驗,將應用初次開發所花費的成本以及隨著軟件演進時的持續成本、產品質量等作為衡量標準來評判這一方法在實際開發中的有效性.
在自動化方面,本文目前僅將IFML 模型應用于測試的生成與執行.在未來工作中,我們將研究通過IFML模型自動化生成應用代碼的方法.由于IFML 模型能夠精確地描述應用的GUI 結構以及其中的工作流傳遞,我們初步計劃為通過IFML 模型,自動化地生成應用的主體骨架,包含:應用中主要的Activity(包含應用的GUI 界面以及界面上的控件元素)、控件元素上的各類事件監聽器以及事件監聽器中各GUI 界面相互跳轉的邏輯代碼.這些代碼可來自于安卓應用與對應擴展后的IFML 模型的資源庫,該資源庫可通過相關工作中介紹的IFML模型抽取技術,對當前開源安卓應用進行抽取獲得.隨后,我們可基于該資源庫,通過結合機器學習和模型驅動開發技術,來實現這些代碼的自動化生成,或是通過尋找相似IFML 模型片段直接獲得實現代碼.隨后,開發人員可對未生成的應用業務邏輯進行補充,形成一個半自動化的開發方式,降低開發中的人工成本,提高效率.