1.1 自動化測試簡介
自動化測試是把以人為驅動的測試行為轉化為機器執行的一種過程。從廣義上來講,一切通過工具(程序)的方式來代替或輔助手工測試的行為都可以看做自動化測試。從狹義上來講,自動化測試就是通過工具記錄或編寫腳本的方式模擬手工測試的過程,通過回放或運行腳本來執行測試用例,從而代替人工對系統的功能進行驗證。
1.2 自動化測試的優點
1)提高效率:通過運行自動化測試腳本,就可以在夜間、午休等時間進行測試用例回歸,實現無人值守測試,大大提高了測試效率。
2)避免重復工作:每發布一個新的版本,其中大部分功能和界面都和上一個版本相似或完全相同,這部分功能就可以用自動化測試,避免人工重復勞動。
3)避免人為出錯:例如忘了執行某些用例,用例執行步驟出錯,輸入數據出錯等。
4)保證每次測試的一致性和可重復性:由于每次自動化測試運行的腳本是相同的,所以每次執行的測試具有一致性,這一點手工測試是很難做到的;而且,由于自動化測試的一致性,很容易發現被測軟件的任何改變。
5)節省人力資源:減少人工,降低成本。
6)克服手工測試的局限性:許多死鎖、資源沖突、多線程等有關的問題 ,通過手工測試很難捕捉到;系統壓力、性能測試,以及需要模擬大數據或大并發用戶等各種測試場景,很難通過手工測試執行;系統可靠性測試,需要模擬系統長時間運行,以驗證系統能否穩定運行,難以通過手工測試執行。
1.3 哪些測試需要用自動化測試解決
并不是所有項目都適合自動化測試,適合自動化測試的項目一般具有如下特點:首先項目周期要長,需求不會頻繁變更;其次系統中多數對象要可以被識別。
你不能指望自動化測試去幫你發現新的bug,自動化測試本身是不具備想象力的(相對于手工測試)。它的優勢在于反復迭代,它的價值產出在于長期的回歸測試,以保證被測產品在版本更新時的穩定性。
一般來說,具備如下特點的測試可以考慮使用自動化測試:
1.大量機械的、重復性的回歸測試;
2.結果的正確性不依賴主觀判斷的測試;
3.需要模擬大量數據、大量并發量的測試;
4.需要不間斷執行的測試;
5.需要短時間內完成的大量測試用例執行(比如完整的功能回歸測試);
測試趨勢應該就是往自動化測試去發展,這個方向是對的,但現實中往往會因為自動化框架的限制等原因,造成問題的漏測,因此適當的進行手工測試也是很有必要的。
2 自動化測試工具
2.1 移動端自動化測試工具的比較
比較流行的移動應用自動化測試工具的比較:
Native apps(原生應用):僅使用Android或iOS的標準SDK編寫的應用;
Web apps(移動瀏覽器應用):用移動平臺的瀏覽器訪問的應用;
Hybrid apps(混合應用):把一個基于webview實現的功能進行包裝的應用。
3 Appium
3.1 Appium簡介
Appium是一個開源的自動化測試工具,其支持iOS和Android平臺上的原生應用、基于移動瀏覽器的應用以及混合應用的測試。
1)Appium的設計理念
1. Appium使用的是移動平臺供應商(iOS的UIAutomation和Android的Instrumentation及UIAutomator)提供的標準自動化測試框架,這就使得你不需要重新編譯或者修改你的app;
2. Appium將不同的移動平臺供應商的自動化測試框架進行一次更高層次的封裝,做成一套統一的API(WebDriverAPI)提供出來,使得你不需要使用一門特定的語言和一個特定的框架去實現和運行你的測試;
3. Appium是開源的;
2)Appium原理框架圖(網上圖片)
從上圖可以看出:
Appium的核心是基于C/S架構的網絡服務器。它接受客戶端(測試
用例實現端)過來的連接,監聽(客戶端發送過來的)命令,在移動設備上運行命令,然后把包含命令運行結果的HTTP響應包發送回客戶端。
Appium使用C/S的架構事實上為我們打開了很多可能性:我們可以在任何支持http 客戶端API的語言上面實現我們的測試代碼;我們可以把服務器端放在跟我們的測試運行機器完全不一樣機器上(例如實現云端測試)。
3)相關組件解釋
1.Appium client:
使用WebDriver庫或者基于WebDriver的擴展庫(統稱Appium客戶端庫)編寫的測試用例。
2.Appium server:
它是個http服務器,它專門接收從Appium client發送過來的命令,同時,它也是bootstrap客戶端。它接收到客戶端的命令后,需要把這些命令發送給目標機器的bootstrap,bootrap接收到命令并轉換為UIAtuomator可以執行的命令。
3.Selenium driver:
即WebDriver,WebDriver是一個用來進行web自動化測試的工具,但是它沒有和任何測試框架進行綁定。它提供了一系列的API對web應用的中界面元素進行定位、模擬用戶操作的API,底層利用JOSN通過HTTP與服務器進行交互。Appium擴展了WebDriver API,使它更適用于移動應用程序的測試。
4.Bootstrap:
Bootstrap是Appium運行在安卓目標測試機器上的一個UiAutomator測試腳本,該腳本所做的事情是在目標機器開啟一個socket服務器來把Appium從PC端過來的命令發送給UiAutomator來執行處理。
3.2 Appium測試環境搭建(Windows)
Appium測試環境的搭建步驟:
1)下載并安裝nodejs
Nodejs的地址:https://nodejs.org/en/download/
2)安裝JDK
安裝過程略,但請注意如下事項。
1.如果選擇64bits的Eclipse,則必須安裝64bits的Java,否則運行Eclipse會出現如下問題:
2.如果導入Android工程,注意JDK版本的選擇,有可能出現如下錯誤:Android requires compiler compliance level5.0 or 6.0. Found '1.8' instead. Please use Android Tools > Fix ProjectProperties
3)安裝Android SDK(可選)
4)安裝Maven(可選)
5)下載并安裝Appium
Appium的下載地址:http://appium.io/,但是一般不會成功。推薦國內下載地址:https://testerhome.com/topics/680
安裝完成之后,將Appium安裝路徑\node_modules\.bin添加到path中,然后在cmd中運行appium-doctor,如果所有的依賴檢查可以通過,表示Appium安裝成功。
4 基于Java的測試框架的選擇
考慮到大家使用的開發語言主要以Java為主,因此測試框架考慮基于Java的JUnit4和TestNG。
二者之間的比較請參考:
這里引用該文章的總結性言論作為我們選擇TestNG這一測試框架的理由:“當我們做完所有特性的對比以后,我建議使用 TestNG 作為 Java 項目的主要單元測試框架,因為 TestNG 在參數化測試、依賴測試以及套件測試(組)方面功能更加強大。TestNG 意味著高級的測試和復雜的集成測試。它更加的靈活,特別是對大的套件測試。另外,TestNG 也涵蓋了 JUnit4 的全部功能。那就沒有任何理由使用 JUnit了。”
另外,由于TestNG和JUnit存在非常多的相似性,二者的代碼常常不需要過多轉換就可以移植,熟悉JUnit的開發人員也不必糾結需要重新學習TestNG;而且,TestNG支持XML文件的配置,非常靈活。
5 腳本錄制
5.1 Appium的腳本錄制
打開Appium.exe,點擊Inspector按鈕進行錄制,Mac版本是具備錄制功能的(網上圖片):
但是Window版本沒有錄制工具,如下圖:
5.2 如何自己實現腳本錄制
可以以考慮使用AccessibilityService,監聽用戶輸入,在onAccessibilityEvent(AccessibilityEvent)方法中解析Event,例如eventtype,className,text,resourceId,index等信息,根據Event類型和其攜帶的控件屬性生成測試代碼,然后在修改成Appium或者其它自動化測試框架需要的腳本。
6 TestNG的編譯和使用
6.1 編譯
TestNG的官網上沒有現成的jar包供下載,但是提供了在Eclipse上使用的插件(更新的地址:http://beust.com/eclipse)。如果需要獲取jar包,可以獲取源代碼并編譯。
關于編譯的步驟,官網上有說明:
TestNGis also hosted on GitHub, where you can download the source and build thedistribution yourself:
$ gitclone git://github.com/cbeust/testng.git $ cdtestng $./build-with-gradle
You willthen find the jar file in the target directory |
其中,build-with-gradle步驟也會去下載gradle工具。
6.2 基本使用
新建Java project,導入TestNG包,編寫測試用例類,在該類中編寫測試用例,編寫方法與使用Junit相似。
運行測試TestNG測試用例:右擊project->run as->TestNG Test
詳細的使用過程請參考:
6.3 TestNG測試用例的命令行運行
TestNG的官方文檔有命令行運行的描述。
在項目中增加testng.xml文件,編譯后,進入工程目錄,輸入命令:
javaorg.testng.TestNG testng.xml |
注:使用前需將testNG的jar包(以及selenium和selenium server需要的jar包)設置在classpath中,上面命令中的org.testng.TestNG是testNG的jar包中的一個類。
6.4 使用testNG.xml文件管理測試用例
1.生成testng.xml文件
右擊Project->TestNG->Convert to TestNG,進入如下界面:
2.測試用例的管理
1. testng.xml文件結構
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM"http://testng.org/testng-1.0.dtd"> <suite name="suitename" junit="false"verbose="3" parallel="false" thread-count="5" configfailurepolicy="skip"annotations="javadoc" time-out="10000"skipfailedinvocationcounts="true" data-provider-thread-count="5" object-factory="classname"allow-return-values="true"> <!-- name參數為必須 --> <suite-files> <suite-filepath="/path/to/suitefile1"></suite-file> <!-- path參數為必須 --> <suite-filepath="/path/to/suitefile2"></suite-file> </suite-files> <parametername="par1" value="value1"></parameter> <!-- name, value參數為必須 --> <parametername="par2" value="value2"></parameter> <method-selectors> <method-selector> <selector-classname="classname" priority="1"></selector-class><!-- name參數為必須 --> <scriptlanguage="java"></script> <!-- language參數為必須 --> </method-selector> </method-selectors> <testname="testename" junit="false" verbose="3"parallel="false" thread-count="5"annotations="javadoc" time-out="10000"enabled="true" skipfailedinvocationcounts="true" preserve-order="true"allow-return-values="true"> <!-- name參數為必須 --> <parametername="par1" value="value1"></parameter> <!-- name, value參數為必須 --> <parametername="par2" value="value2"></parameter> <!-- groups:前提是需要存在classes的組,否則所有方法不被運行 --> <groups> <!--define:定義新的組名 --> <definename="group_name"> <!-- name參數為必須 --> <!--group_name1為測試類中方法的Annotation定義的組名 --> <includename="group_name1" description=""invocation-numbers="" /> <!-- name參數為必須 --> <includename="group_name2" description=""invocation-numbers="" /> </define> <run> <!-- group_name為測試類中定義的組名或者xml中定義的組名 --> <includename="group_name" /> <!-- name參數為必須 --> <excludename="" /> <!-- name參數為必須 --> </run> <dependencies> <groupname="" depends-on=""></group> <!--name,depends-on均為參數為必須 --> <groupname="" depends-on=""></group> </dependencies> </groups> <!-- classes的用法,classes中包含類名,類名底下可以包含方法名或排除方法名 --> <classes> <classname="classname"> <!-- name參數為必須 --> <methods> <parametername="par3" value="value3"></parameter> <includename="method_name" description=""invocation-numbers=""></include> <excludename="method_name"></exclude> </methods> <methods></methods> </class> </classes> <packages> <packagename="" /> <!-- name參數為必須 --> <packagename=""> <includename="" description=""invocation-numbers=""></include> <excludename=""></exclude> </package> </packages> <listeners> <listenerclass-name="classname1" /> <!-- name參數為必須 --> <listenerclass-name="classname2" /> </listeners> </test> <test> </test> </suite> |
2. 使用classes、class標簽進行用例管理
在class標簽中通過name屬性聲明實現了測試方法的類,一個classes標簽可以包含多個class標簽。在class標簽中,還可以通過include和exclude聲明該類中的被包含或者被排除在測試用例中的方法。
3. 使用groups進行用例管理
可以指定test方法屬于哪些group,一個方法可以屬于多個分組。方法屬于哪個分組可以在Java代碼中通過Annotation指定,例如:
@Test(groups = {"group_name1","group_name2"}) Public void func() { } |
指定test方法所屬的分組之后,就可以在testng.xml文件中指定要運行的分組,testng.xml文件修改如下:
其中,define標簽表示在testng.xml文件中根據存在的分組重新定義分組名稱;run標簽定義要運行的分組。
注:
TestNG的group標簽導致的@BeforeMethod方法無效,這樣,如果group里面的方法對@BeforeMethod方法有依賴,可能會導致錯誤。
解決方法:
將@BeforeMethod替換為@BeforeMethod(alwaysRun = true),或者將@BeforeMethod方法也放在group中。
7 測試報告
7.1 TestNG的測試報告
參考:
7.2 ReportNG的編譯
ReportNG的官網上已經申明不再進行維護,當前穩定版本為1.1.4,源代碼已經托管到Github,因此可以根據需要進行定制。
該項目為Maven工程,沒有嘗試進行編譯。但是Eclipse IDE環境已經自帶了Maven插件,可以進行項目的create和build。
注:Maven項目中很多jar包是需要從網絡下載的。
7.3 ReportNG的使用
使用步驟:
1. 作為jar包加入工程的build路徑;
2. 在testng.xml中的suite標簽中添加listener,如下:
<listeners> <listener class-name="org.uncommons.reportng.HTMLReporter"/> <listener class-name="org.uncommons.reportng.JUnitXMLReporter"/> </listeners> |
注:
1. reportNG需要guice的支持,下載地址:http://google-guice.googlecode.com/files/guice-3.0.zip
2. reportNG顯示中文時會有亂碼,解決方法參考:
3. 測試用例跑完之后,可以在test-output目錄的html文件夾找到index.html測試報告。
ReportNG 目前有很多缺點,但是由于提供了源代碼,可以根據需要自己定制。例如,在測試報告中,出錯的用例的高亮顯示沒法做,需要自己去修改ReportNG源碼才能實現;另外,你可以通過代碼修改靜態的html模板去實現報告DIY定制。
8 示例
了解了Appium、TestNG之后,就可以嘗試編寫測試程序了。文檔中測試代碼在GitHub的地址:git@github.com:GitHub-inthewind/CalculatorTestNG.git,是一個基于S2的Calculator編寫的測試用例程序。
8.1 編寫測試用例
1)創建Java工程
2)導入Libs,包括Selenium client庫,SeleniumServer庫,Appium Client庫(可以在Appium的官網上下載,地址:http://appium.io/),testNG,reportNG庫;
3)在Java工程目錄下新建apps目錄,將要測試的APK放在該目錄下;
4)創建class,編寫測試用例
public class AndroidCalculatorTestNG { privateAppiumDriver<AndroidElement> driver;
@BeforeSuite(alwaysRun = true) public void setUp() throws Exception { System.out.println("setUp entry"); // setup appium File classpathRoot = new File(System.getProperty("user.dir")); File appDir = new File(classpathRoot, "apps"); File app = new File(appDir, "Calculator.apk"); DesiredCapabilities capabilities= new DesiredCapabilities(); //project can run,even if the settings of this following statement is wrong capabilities.setCapability("deviceName","0a733f0b"); capabilities.setCapability("platformVersion", "4.4.4"); // setthe APK's path capabilities.setCapability("app", app.getAbsolutePath()); capabilities.setCapability("appPackage", "com.android.calculator2"); capabilities.setCapability("appActivity", "com.android.calculator2.Calculator"); driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); System.out.println("setUp end"); }
@AfterSuite(alwaysRun = true) public void tearDown() throws Exception { System.out.println("tearDown entry"); driver.quit(); System.out.println("tearDown end"); }
@Test(groups = {"funcAdd"}, invocationCount = 1) public void add(){ WebElement num1 = driver.findElementById("digit_1"); num1.click(); WebElement add = driver.findElementById("op_add"); add.click(); WebElement num2 = driver.findElementById("digit_2"); num2.click(); WebElement eq = driver.findElementById("eq"); eq.click();
}
@Test(groups = {"funcSub"}) public void sub(){ WebElement num1 = driver.findElementById("digit_1"); num1.click(); WebElement add = driver.findElementById("op_sub"); add.click(); WebElement num2 = driver.findElementById("digit_2"); num2.click(); WebElement eq = driver.findElementById("eq"); eq.click(); }
} |
5)創建testng.xml文件
testng.xml文件的創建步驟請參考TestNG的編譯和使用章節。
如果需要生成reportNG格式的測試報告,需要對testng.xml文件進行修改,如下:
<?xml version="1.0"encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org /testng-1.0.dtd"> <suite name="Suite"> <!—生成reportNG格式的測試報告--> <listeners> <listener class-name="org.uncommons.reportng .HTMLReporter"/> <listener class-name="org.uncommons.reportng. JUnitXMLReporter"/> </listeners> <test name="Test"> <!—對測試用例進行管理--> <groups> <define name="group-add"> <include name="funcAdd"></include> </define> <run> <include name="group-add"></include> <exclude name="funcSub"></exclude> </run> </groups> <classes> <class name="com.lrm.appium.testng.calculator.AndroidCalculatorTestNG"> </class> </classes> </test> <!-- Test --> </suite> <!-- Suite --> |
6)創建Ant的構建文件build.xml
Build文件的創建請參考Ant的使用章節。
8.2 運行測試用例
將手機與PC通過USB連接,在cmd中,輸入appium,啟動Appium;然后選擇測試項目,右鍵->Run As->TestNG Test。
8.3 異常解決
1)有時候會出現Appium測試用例程序不能運行的情況,提示執行安裝appium settings程序失敗,此時可以看看連接的devices是否在線
2)運行出現NullPointException
問題排查:
查看WorkSpace下的.metadata文件夾下的.log文件,發現有org.eclipse.jdt.junit相關的錯誤,繼續在Eclipse下查找這個jdt.junit相關的插件, Eclipse下缺少org.eclipse.jdt.junit相關的插件,造成用JUnit運行測試用例的時候,報空指針的錯誤。但是Eclipse自帶的JUnit組件確實是安裝了的,有可能是下載的Android開發套件刪除了某些東西導致,于是從Eclipse官網上下載Eclipse版本自己配置環境,編譯運行OK。
原文轉自:https://blog.csdn.net/maetelibom/article/details/51557941