项目地址直达,但是还是希望大家能够看完下面内容再去,非常有利于之后使用该框架,而且也写了好长时间...
日常工作中,经常需要给不同的移动应用开发自动化代码。为了方便自己和其他有自动化需求的小伙伴,这里将平常我经常使用的一套自动化框架整合并放出来,希望可以帮助大家。
框架中集成了以下工具:
mvn test
来跑 TestNG 定义的测试用例。当然了,你依旧可以通过直接运行 TestNG 的 XML 文件来跑。集成 Maven 的优点是方便大家做持续集成。项目中已经集成了 Appium 最新的客户端,初始化 Appium 客户端的代码也已经完成,只需要提供必要的 Capabilities 即可。
初始化代码请参考: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 来管理测试用例,xml 文件放置在 resources 目录下。
一、创建空 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 所需要的参数都放在 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 设备上运行自动化代码,那么app
和appPackage
,appActivity
二者取其一即可,摘抄 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 specifyappPackage
andappActivity
capabilities (see below).UiAutomator2
andXCUITest
allow to start the session withoutapp
orappPackage
. Incompatible withbrowserName
. 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 依赖导入后不需要自定义,在 testng.xml 文件中加入一下代码后即可直接使用:
<listeners>
<listener class-name="org.uncommons.reportng.HTMLReporter"/>
<listener class-name="org.uncommons.reportng.JUnitXMLReporter"/>
</listeners>
生成的报表下图:
Extent Reports 依赖导入以后,可以使用监听器来自定义报表属性。项目中自定义代码参考:ExtentReportListener.java,可以参考该代码来自定义你的 Extent Reports。
同样的,我们也需要在 testng.xml 文件中加入以下代码才可使用:
<listeners>
<listener class-name="com.automation.e2e.ExtentReportListener"/>
</listeners>
生成的报表如下图:
我们有两种方式来运行 testng.xml,一种是直接右键该文件,选择run...
,另一种是使用 Maven 来运行测试。
右键 testng.xml 文件,选择Run ...
来运行
使用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 的自定义监听器。
项目中还加入了常用的工具来方便大家开发,如:
切换到 WebView context
切换到 Native context
向上/向下滚动屏幕
滚动屏幕到指定元素(WebView context)
WebView 下模拟 Native Tap 方法(Android & iOS)
截图
等待元素(WebView context)
这个是非常常用的方法,在写自动化代码的时候经常用到,为显示等待,实现了三种显示等待:
所有的这些实用方法均放在AppiumUtils.java
类中。该类为线程安全的懒加载单例模式,可放心在各种环境下使用,使用方法为:
AppiumUtils appiumUtils = AppiumUtils.getAppiumUtils();
项目中集成了两个例子,一个是 Android Native App 的自动化,一个是 Hybrid App 的自动化。
这里使用安卓自带的计算器来作为 Native 的示例
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"/>
这里我们选用 Chrome 来作为 Hybrid App 的示例。
其中 1,2,3 步骤在 native context 中完成,之后需要切换到 WebView context 中才能继续操作,切换 context 的代码使用的正是上文所提到的AppiumUtils.java
中的切换代码。
<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"/>
这套框架目前我也在使用,依旧在不断完善,这里开源出来,欢迎大家使用并提意见,当然也欢迎大家多多支持。