古銳,肖璞
(三江學(xué)院計算機(jī)科學(xué)與工程學(xué)院,南京 210012)
近些年,手機(jī)端的自動化測試工具和框架逐漸增加,但是它們也存在著一些問題。Appium是手機(jī)端的自動化測試的一個開源框架,它可以針對原生的應(yīng)用和Web應(yīng)用甚至是兩種混合的應(yīng)用進(jìn)行自動化測試[1]。
本課題的研究目的在于通過基于Appium的Android應(yīng)用自動化測試框架的研究,在針對同一款A(yù)ndroid應(yīng)用(可能會進(jìn)行版本迭代或更新)進(jìn)行測試時,能夠?qū)⒁恍┤藶榈氖止y試中效率較低且容易出錯[2]的基本操作,例如安裝啟動應(yīng)用、注冊登錄、進(jìn)行點擊查看、頁面滑動和文本輸入等,通過Appium自動化測試框架編寫自動化的測試用例腳本來執(zhí)行對這些機(jī)械重復(fù)的測試用例的測試,從而提高測試效率。
本論文從自動化測試技術(shù)、Appium工具簡介和Appium設(shè)計理念入手,自主搭建自動化測試所需要的Android環(huán)境和Appium環(huán)境并進(jìn)行了相應(yīng)的配置,通過Eclipse工具編寫符合所測試的Android手機(jī)App的測試用例。
自動化測試指的是針對軟件測試的一種自動實現(xiàn),為了讓人力降低,時間得到保證,并減少一定成本,提高測試的效率,便有了自動化測試這個概念。
自動化測試和手工測試是相輔相成的,在實際生活中,只有在滿足必要的前提條件的情況下我們才能去執(zhí)行自動化測試。可以分以下幾種情況,首先這個項目的測試周期一定要足夠長,因為完成自動化測試的可行性分析,對測試框架進(jìn)行選擇、設(shè)計、編碼和調(diào)試測試腳本等都需要一定的時間和技術(shù)支持。另外,針對某個具體軟件或系統(tǒng),它的需求也不能變動地太頻繁,因為需求變化大,測試用例和測試腳本都需要做出相應(yīng)的調(diào)整,這個時候項目的成本便會提高。還有值得一提的是,編寫的自動化測試腳本最好能夠?qū)崿F(xiàn)很好的復(fù)用,否則自動化測試便不能產(chǎn)生真正意義上的效益。
Appium是支持自動化測試的一個工具,也是支持自動化測試的一個開源框架。Appium支持對iOS平臺和Android平臺上的原生應(yīng)用、Web應(yīng)用和混合應(yīng)用的測試,iOS和Android應(yīng)用是通過Web Driver協(xié)議來驅(qū)動的[3]。另外,Appium支持跨平臺,測試人員可以通過它使用相同的API在不同的平臺上來編寫自動化測試代碼,這樣可以讓代碼反復(fù)使用。
Appium的核心其實是一個Web服務(wù)器,它負(fù)責(zé)接收發(fā)自客戶端的連接,監(jiān)聽這些命令并通過不同框架轉(zhuǎn)變成可以交互的代碼再在測試手機(jī)上執(zhí)行它,然后返回至Appium服務(wù)器運行的結(jié)果,最后再返還HTTP響應(yīng)給客戶端。在這種情形下,實際上我們就可以直接使用帶HTTP客戶端的API的任何語言來寫我們自己的測試代碼。我們可以將服務(wù)器端放置在與測試機(jī)不同的機(jī)器上,只編寫測試代碼,然后使用遠(yuǎn)程云服務(wù)來接收和解釋命令。
Appium Server是通過Node.js寫的,我們可以用源碼編譯的方式或者直接通過NPM($npm install-g appium$appium)命令安裝[3]。Appium還提供了很多基于 WebDriver協(xié)議擴(kuò)展的 C#、PHP、Python、Ruby、JavaScript和Java語言的客戶端庫[3]。這里的WebDriver可以說是用來進(jìn)行自動化測試的一個東西,它提供了一些比如對應(yīng)用中的界面元素進(jìn)行定位和模擬用戶行為等的API,使用Json經(jīng)由HTTP與服務(wù)器進(jìn)行底層的交互。當(dāng)使用Appium時,測試人員可以使用它們來代替常規(guī)的的WebDriver庫。這里我們還需要對Bootstrap.jar有一個了解,首先它是一個UiAutomator測試腳本,由Appium提供,在Android測試機(jī)上運行。它能夠在測試機(jī)上打開一個名為Socket的服務(wù)器,負(fù)責(zé)將Appium從電腦端傳過來的指令發(fā)送到手機(jī)端上,然后通過UiAutomator來執(zhí)行命令和操作。
Appium的工作原理圖和Appium架構(gòu)圖如圖1和圖2所示。
圖1 Appium原理圖
圖2 Appium架構(gòu)圖
Appium的設(shè)計理念可以說是依據(jù)下面幾個方面進(jìn)行描述的,首先,由于在所有的平臺上Appium都是使用標(biāo)準(zhǔn)的自動化API的特性,測試人員不需要為了自動化測試而去重新編譯應(yīng)用(App)或者對測試App進(jìn)行修改[3]。Appium使用了client-server的設(shè)計模式,而且它的客戶端可以是用不同語言編寫的,也就是說,測試人員可以使用自己常用的開發(fā)工具、開發(fā)語言和測試框架去編寫自動化測試腳本代碼,而不會被限制在某種特定語言或者特定的框架上[3]。而且對于測試人員來說,不再需要為了自動化測試而特地去再重寫一套API,因為Webdriver協(xié)議里的API已經(jīng)相當(dāng)完善,只需要借鑒并且修改完善一下就可以使用了。最后,對于移動端的自動化測試來說,它應(yīng)該是開源的。
本次測試的環(huán)境搭建主要分為兩個部分:一是Android環(huán)境,主要用來給模擬器連接和真機(jī)連接提供支持,二是Appium環(huán)境,用來提供測試所需要的工具和環(huán)境。
首先我們需要配置Java開發(fā)的環(huán)境變量,這里我們選擇安裝jdk1.8(win10 64位),可以從官網(wǎng)下載壓縮包,解壓按照步驟運行。安裝在指定位置好了之后,我們需要進(jìn)行簡單的環(huán)境配置,如下所示:
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手機(jī)或者是Android模擬器來執(zhí)行Android移動端應(yīng)用的自動化測試。這時我們需要安裝Android SDK并配置環(huán)境變量。
從官網(wǎng)下載解壓好之后就可以設(shè)置Android環(huán)境變量,配置方法與上述java環(huán)境變量類似(以本機(jī)為例):
1、新建變量名:ANDROID_HOME
變 量 值 :F∶AppiumDesignandroid-sdk_r23.0.2-windowsandroid-sdk-windows
2、編輯變量名:PATH
變量值:
;%ANDROID_HOME%platform-tools;%ANDROID_HOME% ools;
3、找到本機(jī)SDK應(yīng)用程序并啟動它,這里我們還需要安裝一些不同Android版本的模擬器。
在Appium的官網(wǎng)下載與自身操作系統(tǒng)(Win10)對應(yīng)的Appium版本:
將AppiumForWindows_1.4.16.1.zip解壓,然后通過內(nèi)部默認(rèn)安裝程序進(jìn)行安裝。cmd命令輸入“appiumdoctor”,如果Appium所需要的各項環(huán)境都已準(zhǔn)備完成,將出現(xiàn)如圖3所示的提示。
圖3 環(huán)境部署成功圖
下面列舉出本次自動化測試工作中涉及到的測試設(shè)備信息,如表1所示。
表1 測試設(shè)備信息表
本文基于Appium的Android應(yīng)用自動化測試框架的研究,在此針對Android真機(jī)作了連接測試。
真機(jī)連接測試和模擬器連接測試類似,這里我們首先需要打開Android測試機(jī)的USB調(diào)試模式,通過一個數(shù)據(jù)線連接至測試電腦,接著在cmd命令中輸入adb devices查看是否連接成功,在這里需要記錄連接的設(shè)備編號(ef5862e9),如圖4所示。
圖4 真機(jī)連接成功
接下來我們需要在該Android測試機(jī)上安裝需要測試的一款A(yù)pp(新華社客戶端),這里可以通過代碼實現(xiàn),另外我們需要獲取一些相關(guān)的配置信息(被測App的package和activity名稱)。在此我們要用到之前安裝的SDK內(nèi)置的一個叫做aapt的工具,它位于SDK的工具目錄文件夾下,我們通過cmd命令輸入:
aapt dump badging
F∶AppiumDesignappium-workspaceappiumtestAppium_demoappsxhs.apk
(以xhs.apk為例,這里填寫待測apk的存放路徑),等待運行結(jié)束查看:
package∶name='net.xinhuamm.mainclient'
launchable-activity∶name='net.xinhuamm.mainclient.activity.sysconfig.FirstActivity'
這里就是我們需要記錄的package和activity信息,在接下來的代碼中需要填寫,結(jié)果如圖5和圖6所示。
圖5 package運行結(jié)果查看圖
這里我們需要初始化一個Appiumdriver,并在she-zhi()中進(jìn)行一系列的配置,包括需要安裝的測試apk的路徑、包名以及Android的設(shè)備信息等。在tuichu()中我們需要退出driver,如果不退出的話,在下次進(jìn)行測試時,連接服務(wù)器就會受到影響也就是產(chǎn)生錯誤信息。
這里使用@Before和@After兩個方法,它們是Junit4的注解。@Before是一個初始化方法,在每一個測試方法執(zhí)行之前運行一次,而@After則是釋放資源,在每一個測試方法執(zhí)行之后都要運行一次。
真機(jī)連接測試的核心代碼如下:
File pathlujing=new File(System.getProperty("user.dir"));
File applujing=new File(pathlujing,"/apps");//設(shè)置存放路徑
File app=new File(applujing,"xhs.apk");//待測 apk
DesiredCapabilities sz=new DesiredCapabilities();
sz.setCapability("deviceName","ef5862e9");//測試機(jī)設(shè)備名
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);//默認(rèn)端口 4723
System.out.println("App 已經(jīng)安裝!");//輸出 app 成功安裝的提示信息
執(zhí)行成功后在測試機(jī)上會發(fā)現(xiàn)自動安裝了三個東西分別是 xhs.apk、AppiumSetting以及 Unlock。(每次運行都會自動安裝Unlock以及AppiumSetting)
實際效果如圖7所示。
圖7 連接真機(jī)
針對本次Android應(yīng)用App自動化測試,進(jìn)行了如表2所示的測試用例的設(shè)計。
表2 自動化測試用例設(shè)計
在測試用例實現(xiàn)的前期,我們還需要進(jìn)行一些準(zhǔn)備工作,確保我們可以對測試機(jī)上的待測應(yīng)用進(jìn)行簡單的點擊操作。
下面通過連接測試機(jī),自動安裝待測的xhs.apk,針對xhs.apk內(nèi)部頁面進(jìn)行部分控件的點擊(click)操作。首先需要通過Android平臺的UIAutomator[4],也就是android-sdk的一個工具uiautomatorviewer.bat,用它來對測試app的元素(button、text Field等)進(jìn)行抓取,比如通過id、class和text等來確定具體的元素(測試機(jī)需要聯(lián)網(wǎng),否則無法加載頁面內(nèi)容)。
本次測試主要用了獲取name或者id的方式定位到具體的元素,這里以頁面的“學(xué)習(xí)”元素為例,在窗口左邊頁面點擊“學(xué)習(xí)”,右側(cè)會顯示該元素的具體信息,如圖8所示。
本次自動化測試的核心模塊為:注冊登錄、頁面滑動、中英文輸入搜索、屏幕錄制和并行測試。
(1)這里給出左滑的測試代碼,需要調(diào)用下面的方法:
swipeToLeft(driver,1000,2);
核心實現(xiàn)代碼如下:
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)在中英文搜索模塊,需要設(shè)置一些參數(shù): //支持中文輸入 sz.setCapability("unicodeboard","true"); //重置為默認(rèn)輸入法 sz.setCapability("resetKeyboard","true"); 由于輸入測試有時需要輸入中英文等字符,不同Android手機(jī)可能自帶輸入法或者安裝了不同的輸入法,這里我們統(tǒng)一安裝并調(diào)用默認(rèn)的輸入法(Appium unicodeKeyboard)去執(zhí)行操作,具體方法為: excuteAdbShell("adb shell ime set io.appium.android.ime/.UnicodeIME"); (3)屏幕錄制和指定位置截圖,我們使用jilu()和jietu()方法去實現(xiàn): 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("截圖已經(jīng)完成,它位于 "+cPath+"folder"); } } (4)并行測試[5]是指針對兩個不同型號不同版本的Android手機(jī)進(jìn)行自動化測試,這里我們選取Android版本為4.3的vivo手機(jī)和Android版本為6.0的華為手機(jī)作為測試機(jī),這里我們需要打開兩個Appium窗口并設(shè)置不同的連接端口為4723(默認(rèn))和4722。 (1)在一切相關(guān)環(huán)境變量都配置好了之后,打開cmd窗口,輸入appium-doctor,可能會報錯,如圖9所示。 圖9 檢查配置失敗圖 遇到這種情況的解決辦法是將Appium安裝目錄中的.bin添加到環(huán)境變量Path中,以本機(jī)為例就是在Path變量中新增如下信息: F∶AppiumDesignAppiumAppium
ode_modules.bin 再次輸入appium-doctor,就會發(fā)現(xiàn)運行成功,顯示所有環(huán)境已經(jīng)配置完畢。 (2)上面我們提到在每次啟動Appium跑測試用例時都會自動默認(rèn)安裝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)在我們自動化測試的時候,一定要在用例中的相應(yīng)位置添加一些等待界面元素加載或響應(yīng)的等待時間,如果運行報錯,一般情況是找不到元素或者未設(shè)置等待時間,此時可以使用下面的方法避免這個問題: try{Thread.sleep(3000);}//設(shè)置一定的秒數(shù)等待 catch(InterruptedException a) {a.printStackTrace();} (4)常見的報錯問題∶Failed to start an Appium session.Error∶Requested a new session but one was in progress. 解決辦法:關(guān)掉正在運次的Appium服務(wù),在Appium界面的General Settings中勾選Override Existing Session,然后重啟Appium。 本文主要研究了Appium自動化測試框架,同時結(jié)合Android手機(jī)應(yīng)用,針對App進(jìn)行自動化的一個測試。Appium提供的平臺等特性能夠?qū)⒆詣踊瘻y試Android手機(jī)的功能很好的實現(xiàn),在配置好環(huán)境等一切相關(guān)信息之后,通過執(zhí)行用例(可使用不同語言)就能快速地執(zhí)行對測試機(jī)的操作,這無疑讓本次測試工作的效率也得到了一定的提升。 最后,雖然本次自動化測試工作的研究還算有一定的進(jìn)展,但是也遇到和存在著很多的問題,例如運行報錯,功能能夠成功實現(xiàn)或者失敗的驗證邏輯也可以做一個更深的探討與完善等。7 環(huán)境搭建問題與解決方法
8 結(jié)語