整合自動化測試整合框架,整合 Appium+TestNG+ReportNG+ExtentNG+Log4j2+Maven

Microlic發表於2020-08-23

移動應用自動化測試整合框架

專案地址直達,但是還是希望大家能夠看完下面內容再去,非常有利於之後使用該框架,而且也寫了好長時間...

簡介

日常工作中,經常需要給不同的移動應用開發自動化程式碼。為了方便自己和其他有自動化需求的小夥伴,這裡將平常我經常使用的一套自動化框架整合並放出來,希望可以幫助大家。

框架中整合了以下工具:

  1. Appium 使用Appium作為自動化引擎,支援Android,iOS和PC Bowser,程式碼中也寫了兩個例子供大家參考。
  2. TestNG 整合TestNG來管理測試用例。
  3. ReportNG 和 ExtentReports 這裡整合了兩個Report工具,相比TestNG自帶的測試報告,這兩個工具均可以提供非常簡單美觀的測試報告。 為什麼要整合兩個,也是為了不同的需求,ReportNG已經停止維護了,但是我們之前的很多專案中還是使用ReportNG,而且已經和Jenkins進行了深度整合,所以為了保證相容性,還是整合了ReportNG。 ExtentReports是一個比較好的測試報告的代替品,但是需要自己寫監聽器來初始化和自定義報表,框架中已經定義好了,可以直接使用。 兩個報表工具均已經配置好,開箱可用,可以自由選擇哪個報表工具作為最終展現。
  4. Log4j2 + SLF4j 整合Log4j2和SLF4j作為日誌處理工具。
  5. Lombok 整合Lombok簡化程式碼。
  6. Maven 整合Maven和Maven Wrapper。已經在POM檔案中配置好了,可以在命令列直接執行mvn test來跑TestNG定義的測試用例。當然了,你依舊可以通過直接執行TestNG的XML檔案來跑。整合Maven的優點是方便大家做持續整合。

功能

Appium 初始化

專案中已經整合了Appium最新的客戶端,初始化Appium客戶端的程式碼也已經完成,只需要提供必要的Capabilities即可。

初始化Appium client driver

初始化程式碼請參考:InitialTestSuite.java

public void initialDriver(@Optional("http://127.0.0.1:4723/wd/hub") String appiumRemoteURL,
String deviceName,
@Optional("Android") String platformName,
String platformVersion,
@Optional("UIAutomator2") String automationName,
String appName,
String appPackage,
String appActivity) throws MalformedURLException {

DesiredCapabilities desiredCapabilities = null;

if (platformName.equalsIgnoreCase("Android")) {
desiredCapabilities = initialAndroidDriver(deviceName, platformName, platformVersion, automationName, appName, appPackage, appActivity);
} else if (platformName.equalsIgnoreCase("iOS")) {
desiredCapabilities = initialIOSDriver(deviceName, platformName, platformVersion, automationName, appName);
} else {
log.error("For \"platform\" parameter, only support \"Android\" or \"iOS\"");
throw new IllegalArgumentException("For \"platform\" parameter, only support \"Android\" or \"iOS\"");
}

TestCommonSuite.driver = new AndroidDriver(new URL(appiumRemoteURL), desiredCapabilities);

TestCommonSuite.driver.manage().timeouts().implicitlyWait(
Integer.parseInt(resourceBundle.getString("appium.driver.implicitlyWait")),
TimeUnit.SECONDS);
}
如何使用

Appium client driver定義在TestCommonSuite.java的抽象類中,在自動化程式碼執行之前,會用上述程式碼進行初始化,如果想要寫自己的測試用例,就需要整合該抽象類,這樣就可以你自己的類中直接使用driver了。

抽象類程式碼如下:

public abstract class TestCommonSuite {
public static AppiumDriver driver = null;
}

繼承該抽象類即可使用driver:

public class TestClass extends TestCommonSuite {
public void testMethod() throws InterruptedException {
driver.findElementById("testID").click();
}
}

更多Appium知識請參考官網

TestNG 測試用例管理

整合TestNG來管理測試用例,xml檔案放置在resources目錄下。

建立新的TestNG檔案方法

一、建立空XML,加入以下程式碼:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite">
<test verbose="2" preserve-order="true" name="E:/6CodeRepository/AutomationTools/E2EAT/src/main/resources">
</test>
</suite>

注意:<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">這一行程式碼一定要加上,宣告該檔案為TestNG檔案,並提供了程式碼提示和自動完成功能。

二、使用Create TestNG XML外掛

Ctrl+ALT+S開啟設定,選擇Plugins,搜尋Create TestNG XML外掛並安裝,之後就可以在右鍵選單上找到Create TestNG XML選項,使用該選項可以直接在選定目錄下生成testng.xml

注意:所有的自動化程式碼請放置在Maven工程的Test目錄下

初始化Appium Driver

初始化Appium Driver所需要的引數都放在testng.xml檔案裡,示例:

<parameter name="appiumRemoteURL" value="http://127.0.0.1:4723/wd/hub"/>

<!-- Modify parameters according to your needs -->
<parameter name="deviceName" value="Android"/>
<parameter name="platformName" value="Android"/>
<parameter name="platformVersion" value="10.0"/>
<parameter name="automationName" value="UIAutomator2"/>

<!-- App name, not path, put your apk file under resources/apks folder. -->
<parameter name="appName" value=""/>
<!--
Android Only
If there is "appName", will ignore the "appPackage" and "appActivity",
otherwise, will use "appPackage" and "appActivity"
-->
<parameter name="appPackage" value="com.google.android.calculator"/>
<parameter name="appActivity" value="com.android.calculator2.Calculator"/>

需要注意,如果要在Android裝置上執行自動化程式碼,那麼appappPackageappActivity二者取其一即可,摘抄Appium官網說明:

The absolute local path or remote http URL to a .ipa file (IOS), .app folder (IOS Simulator), .apk file (Android) or .apks file (Android App Bundle), or a .zip file containing one of these. Appium will attempt to install this app binary on the appropriate device first. Note that this capability is not required for Android if you specify appPackage and appActivity capabilities (see below). UiAutomator2 and XCUITest allow to start the session without app or appPackage. Incompatible with browserName. See here about .apks file.

更多TestNG知識請參考官網

日誌功能

使用SLF4j + Log4j2作為日誌管理工具,Log4j2的配置檔案放在resources檔案下,摘抄如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Status: TRACE < DEBUG < INFO < WARN < ERROR < FATAL
Log level defined in <logger> will override this configuration.
monitorInterval: Read the configuration file every 300 s.
-->
<Configuration status="WARN" monitorInterval="300">
<properties>
<property name="LOG_HOME">./logs</property>
<property name="FILE_NAME">E2EATLog</property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="RollingFileCommonMSG"
fileName="${LOG_HOME}/${FILE_NAME}.log"
filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i.log">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="6"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
</Appenders>

<Loggers>
<Logger name="com.automation" level="DEBUG" additivity="false" includeLocation="true">
<AppenderRef ref="RollingFileCommonMSG"/>
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.testng" level="DEBUG" additivity="false" includeLocation="true">
<AppenderRef ref="RollingFileCommonMSG"/>
<AppenderRef ref="Console"/>
</Logger>
<Logger name="com.github.appium" level="DEBUG" additivity="false" includeLocation="true">
<AppenderRef ref="RollingFileCommonMSG"/>
<AppenderRef ref="Console"/>
</Logger>
<Root level="DEBUG">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

properties中可以定義log檔案存放目錄和檔名稱,這裡我使用的是專案根目錄下的logs目錄,可以根據時間和大小進行分卷並歸類,如下圖:

你可以自定義該檔案來滿足你的需求。

測試報告

如上文所說,整合了ReportNG和Extent Reports兩個報表工具。

ReportNG

ReportNG依賴匯入後不需要自定義,在testng.xml檔案中加入一下程式碼後即可直接使用:

<listeners>
<listener class-name="org.uncommons.reportng.HTMLReporter"/>
<listener class-name="org.uncommons.reportng.JUnitXMLReporter"/>
</listeners>

生成的報表下圖:

Extent Reports

Extent Reports 依賴匯入以後,可以使用監聽器來自定義報表屬性。專案中自定義程式碼參考:ExtentReportListener.java,可以參考該程式碼來自定義你的Extent Reports。

同樣的,我們也需要在testng.xml檔案中加入以下程式碼才可使用:

<listeners>
<listener class-name="com.automation.e2e.ExtentReportListener"/>
</listeners>

生成的報表如下圖:

Maven

我們有兩種方式來執行testng.xml,一種是直接右鍵該檔案,選擇run...,另一種是使用Maven來執行測試。

執行testng.xml

右鍵testng.xml檔案,選擇Run ...來執行

Maven

使用surefire來將TestNG測試檔案繫結到Maven Test。

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<suiteXmlFiles>
<!-- Location of TestNG xml -->
<suiteXmlFile>${testngFileName}</suiteXmlFile>
</suiteXmlFiles>
<properties>
<property>
<name>suitethreadpoolsize</name>
<value>2</value>
</property>
<!-- Use ReportNG to instead of the default report of TestNG -->
<property>
<name>usedefaultlisteners</name>
<value>false</value>
</property>
<!-- listener -->
<property>
<name>listener</name>
<value>org.uncommons.reportng.HTMLReporter, org.uncommons.reportng.JUnitXMLReporter,
com.automation.e2e.AroundLoggerListener,
com.automation.e2e.ExtentReportListener
</value>
</property>
</properties>
<argLine>-Dfile.encoding=UTF-8</argLine>
<argLine>-Dtestng.dtd.http=true</argLine>
</configuration>
</plugin>

這樣就可以直接在命令列使用mvn test來執行自動化測試,如GIF所示:

自定義監聽器

正如前面所說,我們在使用Extent Reports的過程中是需要使用自定義監聽器的。

TestNG的自定義監聽器非常簡單,寫好了你的監聽器檔案之後,在XML檔案的<listeners></listeners>中加入你的自定義監聽器即可。

專案中加入了兩個自定義監聽器,均可以在專案src\main目錄下找到,一個是Extent Reports的自定義監聽器,另一個是Log的自定義監聽器。

常用工具箱

專案中還加入了常用的工具來方便大家開發,如:

  1. 切換到WebView context

  2. 切換到Native context

  3. 向上/向下滾動螢幕

  4. 滾動螢幕到指定元素(WebView context)

  5. WebView下模擬Native Tap方法(Android & iOS)

  6. 截圖

  7. 等待元素(WebView context)

這個是非常常用的方法,在寫自動化程式碼的時候經常用到,為顯示等待,實現了三種顯示等待:

  1. wait for element present
  2. wait for element visible
  3. wait for element clickable

所有的這些實用方法均放在AppiumUtils.java類中。該類為執行緒安全的懶載入單例模式,可放心在各種環境下使用,使用方法為:

AppiumUtils appiumUtils = AppiumUtils.getAppiumUtils();

目錄結構

-.mvn // 整合Maven Wrapper,可以在根目錄命令列下使用mvnw來代替mvn以避免Maven版本帶來的問題

-document // 文件

-logs // 日誌檔案

-src // 程式碼

​ -main

​ -java // Java程式碼

​ -resources // 資原始檔,配置檔案等

​ -test // 自動化程式碼

-test-output // ReportNG

-test-ouotput2 // ExtentReports

mvnw // mvnw for linux

mvnw.cmd // mvnw for windows

pom.xml

README.md

例項

專案中整合了兩個例子,一個是Android Native App的自動化,一個是Hybrid App的自動化。

Android Native App: Calculator

這裡使用安卓自帶的計算器來作為Native的示例

用例描述
  1. 開啟安卓自帶的計算器
  2. 輸入:1 + 2
  3. 輸出:3
Capabilities

Android 10原生系統中不帶計算器,需要去Google Play下載。

<parameter name="appiumRemoteURL" value="http://127.0.0.1:4723/wd/hub"/>

<!-- Modify parameters according to your needs -->
<parameter name="deviceName" value="Android"/>
<parameter name="platformName" value="Android"/>
<parameter name="platformVersion" value="10.0"/>
<parameter name="automationName" value="UIAutomator2"/>

<!-- App name, not path, put your apk file under resources/apks folder. -->
<parameter name="appName" value=""/>
<!--
Android Only
If there is "appName", will ignore the "appPackage" and "appActivity",
otherwise, will use "appPackage" and "appActivity"
-->
<parameter name="appPackage" value="com.google.android.calculator"/>
<parameter name="appActivity" value="com.android.calculator2.Calculator"/>
執行效果

Hybrid App: Chrome

這裡我們選用Chrome來作為Hybrid App的示例。

用例描述
  1. 開啟Chrome瀏覽器
  2. 跳過配置
  3. 訪問Baidu.com
  4. 輸入Appium到搜尋框並搜尋
  5. 展示搜尋結果

其中1,2,3步驟在native context中完成,之後需要切換到WebView context中才能繼續操作,切換context的程式碼使用的正是上文所提到的AppiumUtils.java中的切換程式碼。

capabilities
<parameter name="appiumRemoteURL" value="http://127.0.0.1:4723/wd/hub"/>

<!-- Modify parameters according to your needs -->
<parameter name="deviceName" value="Android"/>
<parameter name="platformName" value="Android"/>
<parameter name="platformVersion" value="10.0"/>
<parameter name="automationName" value="UIAutomator2"/>

<!-- App name, not path, put your apk file under resources/apks folder. -->
<parameter name="appName" value=""/>
<!--
Android Only
If there is "appName", will ignore the "appPackage" and "appActivity",
otherwise, will use "appPackage" and "appActivity"
-->
<parameter name="appPackage" value="com.android.chrome"/>
<parameter name="appActivity" value="com.google.android.apps.chrome.Main"/>
執行效果

總結

這套框架目前我也在使用,依舊在不斷完善,這裡開源出來,歡迎大家使用並提意見,當然也歡迎大家多多支援。

相關文章