古銳,肖璞
(三江學院計算機科學與工程學院,南京 210012)
近些年,手機端的自動化測試工具和框架逐漸增加,但是它們也存在著一些問題。Appium是手機端的自動化測試的一個開源框架,它可以針對原生的應用和Web應用甚至是兩種混合的應用進行自動化測試[1]。
本課題的研究目的在于通過基于Appium的Android應用自動化測試框架的研究,在針對同一款Android應用(可能會進行版本迭代或更新)進行測試時,能夠將一些人為的手工測試中效率較低且容易出錯[2]的基本操作,例如安裝啟動應用、注冊登錄、進行點擊查看、頁面滑動和文本輸入等,通過Appium自動化測試框架編寫自動化的測試用例腳本來執行對這些機械重復的測試用例的測試,從而提高測試效率。
本論文從自動化測試技術、Appium工具簡介和Appium設計理念入手,自主搭建自動化測試所需要的Android環境和Appium環境并進行了相應的配置,通過Eclipse工具編寫符合所測試的Android手機App的測試用例。
自動化測試指的是針對軟件測試的一種自動實現,為了讓人力降低,時間得到保證,并減少一定成本,提高測試的效率,便有了自動化測試這個概念。
自動化測試和手工測試是相輔相成的,在實際生活中,只有在滿足必要的前提條件的情況下我們才能去執行自動化測試。可以分以下幾種情況,首先這個項目的測試周期一定要足夠長,因為完成自動化測試的可行性分析,對測試框架進行選擇、設計、編碼和調試測試腳本等都需要一定的時間和技術支持。另外,針對某個具體軟件或系統,它的需求也不能變動地太頻繁,因為需求變化大,測試用例和測試腳本都需要做出相應的調整,這個時候項目的成本便會提高。還有值得一提的是,編寫的自動化測試腳本最好能夠實現很好的復用,否則自動化測試便不能產生真正意義上的效益。
Appium是支持自動化測試的一個工具,也是支持自動化測試的一個開源框架。Appium支持對iOS平臺和Android平臺上的原生應用、Web應用和混合應用的測試,iOS和Android應用是通過Web Driver協議來驅動的[3]。另外,Appium支持跨平臺,測試人員可以通過它使用相同的API在不同的平臺上來編寫自動化測試代碼,這樣可以讓代碼反復使用。
Appium的核心其實是一個Web服務器,它負責接收發自客戶端的連接,監聽這些命令并通過不同框架轉變成可以交互的代碼再在測試手機上執行它,然后返回至Appium服務器運行的結果,最后再返還HTTP響應給客戶端。在這種情形下,實際上我們就可以直接使用帶HTTP客戶端的API的任何語言來寫我們自己的測試代碼。我們可以將服務器端放置在與測試機不同的機器上,只編寫測試代碼,然后使用遠程云服務來接收和解釋命令。
Appium Server是通過Node.js寫的,我們可以用源碼編譯的方式或者直接通過NPM($npm install-g appium$appium)命令安裝[3]。Appium還提供了很多基于 WebDriver協議擴展的 C#、PHP、Python、Ruby、JavaScript和Java語言的客戶端庫[3]。這里的WebDriver可以說是用來進行自動化測試的一個東西,它提供了一些比如對應用中的界面元素進行定位和模擬用戶行為等的API,使用Json經由HTTP與服務器進行底層的交互。當使用Appium時,測試人員可以使用它們來代替常規的的WebDriver庫。這里我們還需要對Bootstrap.jar有一個了解,首先它是一個UiAutomator測試腳本,由Appium提供,在Android測試機上運行。它能夠在測試機上打開一個名為Socket的服務器,負責將Appium從電腦端傳過來的指令發送到手機端上,然后通過UiAutomator來執行命令和操作。
Appium的工作原理圖和Appium架構圖如圖1和圖2所示。

圖1 Appium原理圖

圖2 Appium架構圖
Appium的設計理念可以說是依據下面幾個方面進行描述的,首先,由于在所有的平臺上Appium都是使用標準的自動化API的特性,測試人員不需要為了自動化測試而去重新編譯應用(App)或者對測試App進行修改[3]。Appium使用了client-server的設計模式,而且它的客戶端可以是用不同語言編寫的,也就是說,測試人員可以使用自己常用的開發工具、開發語言和測試框架去編寫自動化測試腳本代碼,而不會被限制在某種特定語言或者特定的框架上[3]。而且對于測試人員來說,不再需要為了自動化測試而特地去再重寫一套API,因為Webdriver協議里的API已經相當完善,只需要借鑒并且修改完善一下就可以使用了。最后,對于移動端的自動化測試來說,它應該是開源的。
本次測試的環境搭建主要分為兩個部分:一是Android環境,主要用來給模擬器連接和真機連接提供支持,二是Appium環境,用來提供測試所需要的工具和環境。
首先我們需要配置Java開發的環境變量,這里我們選擇安裝jdk1.8(win10 64位),可以從官網下載壓縮包,解壓按照步驟運行。安裝在指定位置好了之后,我們需要進行簡單的環境配置,如下所示:
1、新建變量名:JAVA_HOME
變量值:C∶Program Files(x86)Javajdk1.8.0_31
2、新建變量名:classpath
變量值:
.;%JAVA_HOME%libdt.jar;%JAVA_HOME%lib ools.jar;
3、編輯變量:PATH
變量值:.;%JAVA_HOME%in;
4、檢查是否配置成功
cmd命令符輸入:java–version。
接下來,我們需要一個能連接電腦的Android手機或者是Android模擬器來執行Android移動端應用的自動化測試。這時我們需要安裝Android SDK并配置環境變量。
從官網下載解壓好之后就可以設置Android環境變量,配置方法與上述java環境變量類似(以本機為例):
1、新建變量名:ANDROID_HOME
變 量 值 :F∶AppiumDesignandroid-sdk_r23.0.2-windowsandroid-sdk-windows
2、編輯變量名:PATH
變量值:
;%ANDROID_HOME%platform-tools;%ANDROID_HOME% ools;
3、找到本機SDK應用程序并啟動它,這里我們還需要安裝一些不同Android版本的模擬器。
在Appium的官網下載與自身操作系統(Win10)對應的Appium版本:
將AppiumForWindows_1.4.16.1.zip解壓,然后通過內部默認安裝程序進行安裝。cmd命令輸入“appiumdoctor”,如果Appium所需要的各項環境都已準備完成,將出現如圖3所示的提示。

圖3 環境部署成功圖
下面列舉出本次自動化測試工作中涉及到的測試設備信息,如表1所示。

表1 測試設備信息表
本文基于Appium的Android應用自動化測試框架的研究,在此針對Android真機作了連接測試。
真機連接測試和模擬器連接測試類似,這里我們首先需要打開Android測試機的USB調試模式,通過一個數據線連接至測試電腦,接著在cmd命令中輸入adb devices查看是否連接成功,在這里需要記錄連接的設備編號(ef5862e9),如圖4所示。

圖4 真機連接成功
接下來我們需要在該Android測試機上安裝需要測試的一款App(新華社客戶端),這里可以通過代碼實現,另外我們需要獲取一些相關的配置信息(被測App的package和activity名稱)。在此我們要用到之前安裝的SDK內置的一個叫做aapt的工具,它位于SDK的工具目錄文件夾下,我們通過cmd命令輸入:
aapt dump badging
F∶AppiumDesignappium-workspaceappiumtestAppium_demoappsxhs.apk
(以xhs.apk為例,這里填寫待測apk的存放路徑),等待運行結束查看:
package∶name='net.xinhuamm.mainclient'
launchable-activity∶name='net.xinhuamm.mainclient.activity.sysconfig.FirstActivity'
這里就是我們需要記錄的package和activity信息,在接下來的代碼中需要填寫,結果如圖5和圖6所示。

圖5 package運行結果查看圖
這里我們需要初始化一個Appiumdriver,并在she-zhi()中進行一系列的配置,包括需要安裝的測試apk的路徑、包名以及Android的設備信息等。在tuichu()中我們需要退出driver,如果不退出的話,在下次進行測試時,連接服務器就會受到影響也就是產生錯誤信息。
這里使用@Before和@After兩個方法,它們是Junit4的注解。@Before是一個初始化方法,在每一個測試方法執行之前運行一次,而@After則是釋放資源,在每一個測試方法執行之后都要運行一次。
真機連接測試的核心代碼如下:
File pathlujing=new File(System.getProperty("user.dir"));
File applujing=new File(pathlujing,"/apps");//設置存放路徑
File app=new File(applujing,"xhs.apk");//待測 apk
DesiredCapabilities sz=new DesiredCapabilities();
sz.setCapability("deviceName","ef5862e9");//測試機設備名
sz.setCapability("platformVersion","4.3");//Android4.3 版本
sz.setCapability("app",app.getAbsolutePath());//獲取路徑
//填寫之前獲取的包名和activity名稱
sz.setCapability("appPackage","net.xinhuamm.mainclient");
sz.setCapability("appActivity","net.xinhuamm.mainclient.activi
ty.sysconfig.FirstActivity");//activity名稱
driver=new AndroidDriver<>(new URL("http∶//127.0.0.1∶4723/wd/hub"),sz);//默認端口 4723
System.out.println("App 已經安裝!");//輸出 app 成功安裝的提示信息
執行成功后在測試機上會發現自動安裝了三個東西分別是 xhs.apk、AppiumSetting以及 Unlock。(每次運行都會自動安裝Unlock以及AppiumSetting)
實際效果如圖7所示。

圖7 連接真機
針對本次Android應用App自動化測試,進行了如表2所示的測試用例的設計。

表2 自動化測試用例設計
在測試用例實現的前期,我們還需要進行一些準備工作,確保我們可以對測試機上的待測應用進行簡單的點擊操作。
下面通過連接測試機,自動安裝待測的xhs.apk,針對xhs.apk內部頁面進行部分控件的點擊(click)操作。首先需要通過Android平臺的UIAutomator[4],也就是android-sdk的一個工具uiautomatorviewer.bat,用它來對測試app的元素(button、text Field等)進行抓取,比如通過id、class和text等來確定具體的元素(測試機需要聯網,否則無法加載頁面內容)。
本次測試主要用了獲取name或者id的方式定位到具體的元素,這里以頁面的“學習”元素為例,在窗口左邊頁面點擊“學習”,右側會顯示該元素的具體信息,如圖8所示。
本次自動化測試的核心模塊為:注冊登錄、頁面滑動、中英文輸入搜索、屏幕錄制和并行測試。
(1)這里給出左滑的測試代碼,需要調用下面的方法:
swipeToLeft(driver,1000,2);
核心實現代碼如下:
public static void swipeToLeft
(AppiumDriver
{
int w=driver.manage().window().getSize().width;
int h=driver.manage().window().getSize().height;
for(int i=0;i { driver.swipe(w*6/7,h/2,w/7,h/2,during); try{Thread.sleep(2000);} catch(InterruptedException e) {e.printStackTrace();} } } (2)在中英文搜索模塊,需要設置一些參數: //支持中文輸入 sz.setCapability("unicodeboard","true"); //重置為默認輸入法 sz.setCapability("resetKeyboard","true"); 由于輸入測試有時需要輸入中英文等字符,不同Android手機可能自帶輸入法或者安裝了不同的輸入法,這里我們統一安裝并調用默認的輸入法(Appium unicodeKeyboard)去執行操作,具體方法為: excuteAdbShell("adb shell ime set io.appium.android.ime/.UnicodeIME"); (3)屏幕錄制和指定位置截圖,我們使用jilu()和jietu()方法去實現: public void jilu()throws IOException { Runtime ss=Runtime.getRuntime(); ss.exec("cmd.exe/C adb shell screenrecord/sdcard/test.mp4");//版本>4.4 } public static void jietu(TakesScreenshot drivername,String fname) { String cPath=System.getProperty("user.dir");//獲取路徑 File rcrFile=drivername.getScreenshotAs(OutputType.FILE); try { System.out.println("截圖保存的路徑是∶"+current-Path+"/"+filename); FileUtils.copyFile(rcrFile,new File(cPath+"\"+fname)); }catch(IOException e) { System.out.println("不能保存截圖"); e.printStackTrace(); }finally { System.out.println("截圖已經完成,它位于 "+cPath+"folder"); } } (4)并行測試[5]是指針對兩個不同型號不同版本的Android手機進行自動化測試,這里我們選取Android版本為4.3的vivo手機和Android版本為6.0的華為手機作為測試機,這里我們需要打開兩個Appium窗口并設置不同的連接端口為4723(默認)和4722。 (1)在一切相關環境變量都配置好了之后,打開cmd窗口,輸入appium-doctor,可能會報錯,如圖9所示。 圖9 檢查配置失敗圖 遇到這種情況的解決辦法是將Appium安裝目錄中的.bin添加到環境變量Path中,以本機為例就是在Path變量中新增如下信息: F∶AppiumDesignAppiumAppium
ode_modules.bin 再次輸入appium-doctor,就會發現運行成功,顯示所有環境已經配置完畢。 (2)上面我們提到在每次啟動Appium跑測試用例時都會自動默認安裝Unlock以及AppiumSetting,這里有個辦法可以解決這個問題:找到Appium的安裝目錄,用記事本打開android.js文件,注釋掉自動安裝unlock和setting兩個app的代碼: F∶AppiumDesignAppiumAppium
ode_modulesappi -umlibdevicesandroid 如圖10所示。 圖10 修改配置文件圖 注釋其中的幾行: this.pushSettingsApp.bind(this), this.pushUnlock.bind(this), this.unlock.bind(this), (3)在我們自動化測試的時候,一定要在用例中的相應位置添加一些等待界面元素加載或響應的等待時間,如果運行報錯,一般情況是找不到元素或者未設置等待時間,此時可以使用下面的方法避免這個問題: try{Thread.sleep(3000);}//設置一定的秒數等待 catch(InterruptedException a) {a.printStackTrace();} (4)常見的報錯問題∶Failed to start an Appium session.Error∶Requested a new session but one was in progress. 解決辦法:關掉正在運次的Appium服務,在Appium界面的General Settings中勾選Override Existing Session,然后重啟Appium。 本文主要研究了Appium自動化測試框架,同時結合Android手機應用,針對App進行自動化的一個測試。Appium提供的平臺等特性能夠將自動化測試Android手機的功能很好的實現,在配置好環境等一切相關信息之后,通過執行用例(可使用不同語言)就能快速地執行對測試機的操作,這無疑讓本次測試工作的效率也得到了一定的提升。 最后,雖然本次自動化測試工作的研究還算有一定的進展,但是也遇到和存在著很多的問題,例如運行報錯,功能能夠成功實現或者失敗的驗證邏輯也可以做一個更深的探討與完善等。7 環境搭建問題與解決方法


8 結語