最近群里經常有人會問到關於maven構建Appium測試項目以及使用testNG生成測試報告的問題,試着搭建了一下,下面是過程:
jdk安裝過程我這里就不說了
一、下載eclipse,推薦下載Eclipse Luna java EE版本,自帶maven插件,比較穩定。Eclipse Luna java EE版64位下載地址:http://ftp.yz.yamagata-u.ac.jp/pub/eclipse//technology/epp/downloads/release/luna/SR2/eclipse-jee-luna-SR2-win32-x86_64.zip
二、下載Maven並配置環境變量
從maven官網下載maven程序包:http://apache.opencas.org/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.zip,下載后解壓,例如我的目錄結構是:
配置環境變量MAVEN_HOME,變量值為maven的根目錄:D:\Program Files\apache-maven-3.3.9,在PATH中添加bin的路徑:D:\Program Files\apache-maven-3.3.9\bin,
三、配置settings.xml文件,打開maven conf目錄下的settings.xml文件,配置maven本地倉庫地址,我配置的是F:\repository
我還配置了鏡像的地址,因為從默認的中央倉庫下載依賴包太慢了,在settings.xml中加入下面的代碼:

1 <mirrors> 2 <!-- mirror | Specifies a repository mirror site to use instead of a given 3 repository. The repository that | this mirror serves has an ID that matches 4 the mirrorOf element of this mirror. IDs are used | for inheritance and direct 5 lookup purposes, and must be unique across the set of mirrors. | --> 6 <mirror> 7 <id>nexus-osc</id> 8 <mirrorOf>central</mirrorOf> 9 <name>Nexus osc</name> 10 <url>http://maven.oschina.net/content/groups/public/</url> 11 </mirror> 12 <mirror> 13 <id>nexus-osc-thirdparty</id> 14 <mirrorOf>thirdparty</mirrorOf> 15 <name>Nexus osc thirdparty</name> 16 <url>http://maven.oschina.net/content/repositories/thirdparty/</url> 17 </mirror> 18 </mirrors>
推薦幾個國內的鏡像地址:
http://maven.oschina.net/content/groups/public/
http://maven.oschina.net/content/repositories/thirdparty/
http://repo2.maven.org/maven2/
如果在下載的時候還是覺得慢的話,請自行百度其他地址。
打開Eclipse,在菜單選擇:windows->Preference->Maven->User Settings,在右側User Settings選擇剛才的settings.xml文件:
配置后,下面步驟在pom.xml配置的依賴包就會從遠程倉庫下載到本地配置的倉庫:F:\repository
四、安裝Eclipse testNG插件,在菜單欄選擇help->Eclipse Maketplace,搜索testng,安裝,重啟Eclipse
五、開始創建Maven工程,選擇Archetype,輸入Group Id、Artifact Id,finish創建完成,如下圖:
創建完成后是這樣的:
六、配置依賴包,Appium需要三個包:appium client、selenium client、selenium server,如果我們不用maven構建工程,那么我們需要去下載這三個包,然后添加到我們的工程中,而maven不需要了,只需要配置依賴關系就可以了,我們可以在maven倉庫中搜索我們需要的包,把他們的依賴關系寫到pom.xml文件中:
maven倉庫地址:http://mvnrepository.com/,例如搜索appium,就可以搜索到appium java client的包,選擇最新的包,把依賴關系粘貼打pom.xml中,selenium client和selenium server只需要配置一個selenium依賴就行了,配置后的pom.xml文件如下:

1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>com.zdx.appium</groupId> 6 <artifactId>num1</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <packaging>jar</packaging> 9 10 <name>num1</name> 11 <url>http://maven.apache.org</url> 12 13 <properties> 14 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 15 </properties> 16 17 <dependencies> 18 <dependency> 19 <groupId>junit</groupId> 20 <artifactId>junit</artifactId> 21 <version>3.8.1</version> 22 <scope>test</scope> 23 </dependency> 24 <dependency> 25 <groupId>io.appium</groupId> 26 <artifactId>java-client</artifactId> 27 <version>3.4.0</version> 28 </dependency> 29 <dependency> 30 <groupId>org.testng</groupId> 31 <artifactId>testng</artifactId> 32 <version>6.9.10</version> 33 </dependency> 34 35 </dependencies> 36 </project>
配置后保存,會自動更新依賴包,如果沒有更新也可以在右鍵選中工程,選擇Maven-Update Project,進行更新。更新完成后,你就發現你的Maven Dependencies多了很多jar包
七、創建TestNG測試類,因為是Appium項目,所以我把源代碼放在了src/test/java目錄下,選中目錄,右鍵選擇New->Other->TestNG->TestNG Class
創建完成后的目錄結構:
八、下面就開始寫Appium代碼吧,下面是我寫的一個demo,app是我自己寫的一個測試demo
APP截圖:
測試代碼:

1 package com.zdx.appium.num1; 2 3 import org.testng.Assert; 4 import org.testng.annotations.Test; 5 import org.testng.annotations.BeforeTest; 6 import org.testng.annotations.AfterTest; 7 8 import io.appium.java_client.AppiumDriver; 9 import io.appium.java_client.android.AndroidDriver; 10 import io.appium.java_client.android.AndroidElement; 11 12 import java.io.File; 13 import java.io.UnsupportedEncodingException; 14 import java.net.URL; 15 import java.sql.Driver; 16 import java.sql.Time; 17 import java.util.List; 18 import java.util.Random; 19 20 import mx4j.log.Log; 21 22 import org.apache.bcel.generic.RETURN; 23 import org.junit.After; 24 import org.junit.Before; 25 import org.openqa.selenium.By; 26 import org.openqa.selenium.WebElement; 27 import org.openqa.selenium.logging.LogEntry; 28 import org.openqa.selenium.logging.LoggingHandler; 29 import org.openqa.selenium.logging.LoggingPreferences; 30 import org.openqa.selenium.logging.Logs; 31 import org.openqa.selenium.remote.DesiredCapabilities; 32 import org.openqa.selenium.remote.RemoteWebDriver; 33 import org.openqa.selenium.remote.server.log.LoggingManager; 34 import org.openqa.selenium.remote.server.log.LoggingOptions; 35 import org.testng.asserts.LoggingAssert; 36 37 38 public class NumFirst { 39 private AndroidDriver<AndroidElement> driver; 40 @BeforeTest 41 public void setUp() throws Exception{ 42 /* File classpathRoot = new File(System.getProperty("user.dir")); 43 System.out.println(classpathRoot); 44 File appDir = new File(classpathRoot, "/apps"); 45 File app = new File(appDir, "");*/ 46 DesiredCapabilities capabilities = new DesiredCapabilities(); 47 48 capabilities.setCapability("deviceName","udid"); 49 capabilities.setCapability("platformVersion", "4.4"); 50 capabilities.setCapability("udid","YT91050HXZ"); 51 //capabilities.setCapability("app", app.getAbsolutePath()); 52 capabilities.setCapability("appPackage", "com.example.yadudemo"); 53 capabilities.setCapability("appActivity", ".MainActivity"); 54 //capabilities.setCapability("appActivity", ".ui.activity.UPlusMainActivity"); 55 driver = new AndroidDriver<>(new URL("http://127.0.0.1:4726/wd/hub"), capabilities); 56 } 57 @Test 58 public void test() throws UnsupportedEncodingException { 59 //驗證APP啟動成功,並且MainActivity打開 60 if(activityVerify(8000, driver, ".MainActivity")==true) 61 { 62 System.out.println(driver.currentActivity().toString()); 63 Assert.assertEquals(driver.currentActivity().toString(), ".MainActivity"); 64 AndroidElement bt_config = driver.findElementByName("配置"); 65 bt_config.click(); 66 //驗證ConfigActivity打開 67 if(activityVerify(3000, driver, ".ConfigActivity")==true) 68 { 69 Assert.assertEquals(driver.currentActivity().toString(), ".ConfigActivity"); 70 List<AndroidElement> et_List = driver.findElementsByClassName("android.widget.EditText"); 71 //輸入密碼 72 et_List.get(1).clear(); 73 et_List.get(1).sendKeys("12345678"); 74 //驗證輸入密碼正確 75 Assert.assertEquals(et_List.get(1).getText(), "12345678"); 76 //輸入超時時間 77 et_List.get(2).clear(); 78 et_List.get(2).sendKeys("12"); 79 //驗證超時時間輸入正確 80 Assert.assertEquals(et_List.get(2).getText(), "12"); 81 //如果button被鍵盤遮擋,關閉鍵盤 82 if(driver.findElementsByName("開始配置").isEmpty()) 83 { 84 driver.pressKeyCode(4); 85 } 86 //點擊開始配置 87 AndroidElement bt_start_config = driver.findElementByName("開始配置"); 88 bt_start_config.click(); 89 } 90 } 91 //關閉APP 92 closeApp(); 93 //驗證APP已經關閉 94 Assert.assertNotEquals(driver.currentActivity().toString(), ".ConfigActivity"); 95 Assert.assertNotEquals(driver.currentActivity().toString(), ".MainActivity"); 96 } 97 98 @AfterTest 99 public void tearDown() { 100 driver.quit(); 101 } 102 //線程等待方法 103 public void appWait(long time) 104 { 105 try { 106 Thread.sleep(time); 107 } catch (InterruptedException e) { 108 // TODO Auto-generated catch block 109 e.printStackTrace(); 110 } 111 } 112 //關閉APP方法 113 public void closeApp() 114 { 115 for(int h=0;h<6;h++) 116 { 117 driver.pressKeyCode(4); 118 } 119 } 120 //驗證activity方法 121 public Boolean activityVerify(long time,AndroidDriver<AndroidElement> tdriver,String activity) 122 { 123 for(int i=1;i<time/1000;i++){ 124 appWait(1000); 125 if(tdriver.currentActivity().equals(activity)) 126 { 127 return true; 128 } 129 } 130 System.out.println("can not find "+activity); 131 return false; 132 133 } 134 }
啟動Appium Server,連接手機(我手機已經安裝了測試demo APP),右鍵選中num1工程,選擇Run As->TestNG Test,運行后,會在工程目錄下創建一個test-output的文件夾,打開文件夾下的index.html可以查看測試結果,也可以在Eclipse的Console中查看結果,如下圖:
這個報告很簡陋,下面開始用ReportNG替換TestNG的報告
九、使用ReportNG生成報告
1、添加依賴,在pom.xml文件中添加下列依賴關系:

1 <dependency> 2 <groupId>org.uncommons</groupId> 3 <artifactId>reportng</artifactId> 4 <version>1.1.4</version> 5 <scope>test</scope> 6 <exclusions> 7 <exclusion> 8 <groupId>org.testng</groupId> 9 <artifactId>testng</artifactId> 10 </exclusion> 11 </exclusions> 12 </dependency> 13 <dependency> 14 <groupId>com.google.inject</groupId> 15 <artifactId>guice</artifactId> 16 <version>4.0</version> 17 <scope>test</scope> 18 </dependency>
2、配置maven-surefire-plugin並加入reportNG listenser

1 <build> 2 <plugins> 3 <plugin> 4 <groupId>org.apache.maven.plugins</groupId> 5 <artifactId>maven-surefire-plugin</artifactId> 6 <version>2.17</version> 7 <configuration> 8 <suiteXmlFiles> 9 <suiteXmlFile>xmlfile/testng.xml</suiteXmlFile> 10 </suiteXmlFiles> 11 </configuration> 12 </plugin> 13 <plugin> 14 <groupId>org.apache.maven.plugins</groupId> 15 <artifactId>maven-surefire-plugin</artifactId> 16 <version>2.19.1</version> 17 <configuration> 18 <properties> 19 <property> 20 <name>usedefaultlisteners</name> 21 <value>false</value> 22 </property> 23 <property> 24 <name>listener</name> 25 <value>org.uncommons.reportng.HTMLReporter, org.uncommons.reportng.JUnitXMLReporter</value> 26 </property> 27 </properties> 28 <workingDirectory>target/</workingDirectory> 29 </configuration> 30 </plugin> 31 </plugins> 32 </build>
注意這句:<suiteXmlFile>xmlfile/testng.xml</suiteXmlFile>,我在工程目錄下新建了一個文件夾,把testng的xml文件都放在這個目錄下,如果有多個testng.xml文件的話,這樣更直觀,如果只有一個的話,不建文件夾也可以。
如果看不懂的話,請百度maven-surefire-plugin參數說明
3、更新一下Maven Project,然后右鍵選中Maven工程,選擇Run As->Maven Test,運行成功后,在target目錄下創建了一個surefire-reports目錄,打開它下面的html文件夾,打開indel.xml,就可以看到相對美觀的報告形式了:
reportNG報告樣式是可以自定義的,我的報告中還有亂碼,以后會慢慢研究。