说明
本次分享Android端APP自动化测试Excel执行逻辑,整体逻辑与Web端类似,没看过的读者可看这里 =========>>
一种很轻松的Excel关键字方式进行网页Web自动化测试(Java+Selenium+TestNG+Excel)
当然也存在差异的部分,本文会详细介绍该部分------------------(PS:作者使用版本appium框架 java版本8.0.0)
可能小伙伴会有疑问,整体框架看着可能有点臃肿(cn.nhdc.cloud.testscripts包下为测试脚本部分),代码不够简洁。
- 那是因为:
*设计之初,为提供测试人员一种只专注业务逻辑测试代码,快捷开发测试脚本(testcase)又同时加强代码可读性,case高可维护性的一种方案,同时考虑不同应用设备端、不同类型的测试,提供统一的一套框架。但前景美好,现实很残酷。。。跑题了
,总而言之,为了能快速落地,形成了目前这套框架,即不是专门为了Excel测试设计的,是为了多种形式调用测试及扩展开发设计的,so… **
总之,就在此基础上,提供Excel执行测试的一种方案,同时结合EasyExcel工具提供用户快速编辑测试用例,整体形成一个闭环且相对便利的App/Web自动化测试解决方案
- 文章作者:@随心自然fqc , 转载时,请注明来源,注明作者,这是对文章作者的尊重,也是对知识的尊重。
整体图解
主要内容
1、测试调用方式
与Web类型调用一致,同时testUseBaseMethod(username,password)
调用基类关键字操作方法。
import cn.nhdc.cloud.modules.casemanage.model.vo.TestCaseVo;
import cn.nhdc.cloud.testscripts.config.AppiumCapabilities;
import cn.nhdc.cloud.testscripts.config.LocateType;
import cn.nhdc.cloud.testscripts.listener.ExtentTestNGIReporterListener;
import cn.nhdc.cloud.testscripts.testcase.base.AndroidTestBase;
import org.testng.annotations.Listeners;
import org.testng.annotations.Optional;
import org.testng.annotations.Test;
import java.util.List;
/**
* Android类型 Excel执行方式 自动化测试demo <br>
* Method 1 : {@link #testExcelExcute} 正向逻辑执行 <br>
* Method 2 : {@link #testExcelInvokeExcute} 反射逻辑执行 <br>
* Method 3 : {@link #testUseBaseMethod} 同时可调用基类方法 <br>
*
* ps: 以上2种方式 原理不同 但执行效果类似 具体选择哪种取决于调用者意愿
*
* @author Fan QingChuan
*/
@Test(description = "Excel方式自动化测试示例-正向逻辑&反射执行逻辑")
@Listeners(value = ExtentTestNGIReporterListener.class)
public class ExcelAndroidTestDemo extends AndroidTestBase {
@Test(description = "正向逻辑: 操作方法封装在 AndroidTestBase 中, 测试用例中可直接调用 解析Excel -> caseSteps 根据遍历操作编码switch执行各项操作")
void testExcelExcute(
@Optional("C:\\Users\\allen\\Desktop\\自动化测试_测试用例_2022_07_04_150350_623.xlsx") String fileName,
@Optional("testcase")String sheetName,@Optional("null")Integer headerRowNumber) {
List<TestCaseVo> caseVoList = analysisExcelUiCase(fileName, sheetName, headerRowNumber);
excuteExcelUiTest(caseVoList);
}
@Test(description = "反射逻辑: 操作封装在 AndroidCommon 通过 AndroidTestBase 中反射获取 AndroidBasePage.class 并实例化 再根据操作编码+分类枚举 获取对应方法 并反射(invoke)执行测试")
void testExcelInvokeExcute(
@Optional("C:\\Users\\allen\\Desktop\\自动化测试_安卓APP类型测试用例_2022_07_08_133321_663.xlsx") String fileName,
@Optional("testcase")String sheetName,@Optional("null")Integer headerRowNumber)
throws IllegalAccessException, InstantiationException {
List<TestCaseVo> caseVoList = analysisExcelUiCase(fileName, sheetName, headerRowNumber);
invokeExcelUiTest(caseVoList);
}
@Test
void testUseBaseMethod(@Optional("ATE002")String username,@Optional("a123456")String password) {
//开启Appium服务
startDefaultBaseService();
//初始化AndroidDriver
initBaseAndroidDriver(AppiumCapabilities.getHarmonyJx());
//点击同意隐私协议
clickNegatively(LocateType.ID,"cn.newhope.qc:id/tv_privacy_agree");
//输入用户名
inputText(LocateType.ID,"cn.newhope.qc:id/etAccount",username);
//输入密码
inputText(LocateType.ID,"cn.newhope.qc:id/etPassword",password);
//点击勾选同意隐私政策
click(LocateType.ID,"cn.newhope.qc:id/protocolCb");
//点击登录
click(LocateType.ID,"cn.newhope.qc:id/btnLogin");
//断言toast
assertToastHasAppeared(10,"toast消息文本");
}
}
2、执行测试逻辑
整体执行逻辑与Web一致,只是在App自动化方面,Appium ,执行测试前需开启Appium服务(AppiumDriverLocalService),并实例化具体不同测试端的Driver。
强烈建议:看过Web端相关逻辑再来看Android端 传送门 >> 网页Web端Excel自动化测试(Java+Selenium+TestNG+Excel)
- 先来App通用的测试基类–AppTestBase, 主要提供创建/关闭Appium服务
import cn.hutool.core.util.ObjectUtil;
import cn.nhdc.cloud.modules.casemanage.model.vo.TestCaseVo;
import cn.nhdc.cloud.testscripts.config.ReportLog;
import cn.nhdc.cloud.testscripts.testcase.base.common.AppCommon;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException;
import io.appium.java_client.service.local.flags.ServerArgument;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import java.net.URL;
import java.util.List;
import java.util.Map;
/**
* App相关测试通用Base <br>
* 继承该类需实现抽象方法-Excel执行测试方法 {@link AppTestBase#excuteExcelUiTest(List)} {@link AppTestBase#invokeExcelUiTest(List)} <br>
* 该类只提供AppiumDriverLocalService {@link AppTestBase#service} 不提供具体类型baseDriver <br>
* 即:
* 测试case应早已明确该从事具体类型Driver的测试,应选择继承该类子类 {@link AndroidTestBase} 或 {@link IOSTestBase} 或其他
*
* @author Fan QingChuan
* @since 2022/6/7 16:53
*/
public abstract class AppTestBase extends WebTestBase implements AppCommon {
private static final ReportLog reportLog = new ReportLog(AppTestBase.class);
public static final int TIME_OUT = 5;
public static final int SLEEP_TIME = 300;
public static final int DEFAULT_PORT = 4723;
public static final String DEFAULT_IP = "127.0.0.1";
protected AppiumDriverLocalService service;
@Override
public abstract void excuteExcelUiTest(List<TestCaseVo> caseVoList);
@Override
public abstract void invokeExcelUiTest(List<TestCaseVo> caseVoList) throws InstantiationException, IllegalAccessException;
public void startDefaultBaseService() {
try {
service = buildDefaultAppiumService(); //创建默认的AppiumDriverLocalService
checkPortAndKillTask(DEFAULT_PORT); //检查并KILL端口进程任务 默认4723
service.start(); //开启服务
reportLog.info("开启Appium本地服务 ========== >> URL: {}",service.getUrl());
} catch (AppiumServerHasNotBeenStartedLocallyException e) {
e.printStackTrace();
}finally {
reportLog.info("检查服务是否正常运行 ========== >> [{}]",service.isRunning());
}
}
public void startCustomBaseService(int port, String ipAddress, Map<ServerArgument,String> arguments) {
try {
service = buildCustomAppiumService(port,ipAddress,arguments); //根据配置创建AppiumDriverLocalService
checkPortAndKillTask(port);
service.start();
reportLog.info("开启Appium本地服务 ========== >> URL: [{}]",service.getUrl());
} catch (AppiumServerHasNotBeenStartedLocallyException e) {
e.printStackTrace();
}finally {
reportLog.info("服务是否正常开启 ========== >> [{}]",service.isRunning());
}
}
public URL getServiceUrl() {
if (service.isRunning()) {
return service.getUrl();
}else {
throw new RuntimeException("AppiumDriverLocalService service 未启动!");
}
}
protected void closeBaseAppium