对于测试框架搭建,无论是Web端还是移动端的UI自动化测试,除去测试对象和框架本身的API差异,在思路上其实都是一样的,无非就是元素查找、元素操作、对比结果、输出报告、用例管理等等,然而这么“折腾”的在原有框架上再封装搭建这么一套测试框架的根本目的在于更好的管理你的测试项目,方便后期维护……那么如何快速搭建一个基于UiAutomator2.0的自动化测试框架呢?
一、准备工作
还是老规矩,在开始自己项目的自动化测试之前,我们最好已经完成了下面的准备工作:
1、熟悉待测应用
对待测应用整体功能和业务逻辑有比较清晰的认识。
2、编写应用的自动化测试用例大纲
这一步主要是让我们在编码前,按应用的功能或者操作流程将可实施自动化测试的部分划分出来。
3、选择合适的工具和框架
这里就不用像Web端那样有那么多选择了,基于UiAutomator2.0的话,使用Android Studio作为开发工具,默认使用的是Junit4来管理用例,不过min SDK还是要选择的,至少得是16以上吧,一般推荐18。
二、实现步骤
项目结构:
1>创建测试用例的父类BaseCase类:
每个测试用例类都继承自BaseCase类,那么就可以将用例中的公共部分放到BaseCase类中去实现,从而简化代码结构和减少代码冗余,比如:
a. 在BaseCase类中实现Junit4中的@BeforeClass, @AfterClass(整个测试项目中只运行一次,它们对应的方法必须是静态方法)和@Before, @After(每个测试方法开始前后都运行一次)注解对应的方法;
b. 一些常用的与用例相关的方法;
c. 公共变量等。
public class BaseCase {
public static String pkgName= "";
public static UIDevice mDevice;
@BeforeClass
public static void setup(){
//测试项目开始前运行(仅一次),如清除缓存数据、安装应用等
}
@AfterClass
public static void teardown(){
//测试项目结束时运行(仅一次),如卸载应用等
}
@Before
public void initTest(){
//测试开始前运行(每个@Test运行前都会运行一次),如打开应用等
}
@After
public void close(){
//测试结束后(每个@Test结束后都会运行一次),如退出应用等
}
……
2>创建用例的操作类TestAction类:
TestAction类主要封装一些界面动作,比如点击、输入、移动、刷新等,与界面用户操作(动作)相关的都可以封装在这个类里面。
public class TestAction {
public static void click(Object obj){
if(obj != null){
log.i( "点击对象:" + getText(obj));
if(obj instanceof UiObject2) {
((UiObject2)obj).click();
}
}else{
log.w( "未找到点击对象");
}
}
……
}
3>元素对象管理:
(借用之前搭建Web自动化测试框架的说明,思想都是一样的)
前面已经封装了BaseCase类和操作类,但是页面的元素对象该如何管理呢?这可能要根据项目的大小和元素的多少来定,下面我提供几种常用方式:
a. 直接将元素定位的id 、name或 xpath写在代码中;
b. 将元素定位的表达式提取出来存放在文本、excel、XML、yaml或json中;
c. 将元素定位的表达式提取出来存放到数据库中;
将元素定位写在代码中,好处就不言而喻了,方便调试嘛,但是对于页面元素上万这种就不推荐了,元素对象将会变得很难管理(估计代码中会遗留很多无用对象),但是对于页面元素不多的情况下还是推荐它的,下面就用PageObject的方式将元素定位写在代码中举例:
public class MainPage extends BasePage {
private UiDevice mDevice;
public MainPage(UiDevice mDevice){
super(mDevice);
this.mDevice = mDevice;
}
public UiObject2 getSettingBtn(){
BySelector by = By.res("com.alany.demo:id/btnSetting");
return hasObject(mDevice,by) ? mDevice.findObject(by) : null;
}
public UiObject2 getCustomBtn(){
BySelector by = By.text("自定义按钮");
return hasObject(mDevice,by) ? mDevice.findObject(by) : null;
}
}
4>用例编写:
根据页面创建测试用例类,由于Junit4没有像TestNG那样提供xml管理用例,所有测试方法一般都在一个测试类中,比如基于版本V1的测试类V1SanityTest。
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class V1SanityTest extends BaseCase{
@Test
public void test001(){
//具体的测试实现
}
@Test
public void test002(){
//具体的测试实现
}
}
5>Log管理
对于log的输出,当然希望是能输出到本地文件中,那么使用Android的Log类就爱莫能助了,这个就可以结合log4j来实现了,对于error级别的log还可以截图。
public class LogUtil {
private String tag;
private String logPath = BaseCase.AD_HOME_PATH + File.separator + "screenshot" + File.separator;
private Logger logger;
public LogUtil(String tag) {
this.tag = tag;
logger = getLogger(tag);
File logFile = new File(logPath);
if (! logFile.exists()) {
logFile.mkdir();
}
}
public void i(Object msg){
Log.i(this.tag, msg + "");
logger.info(msg);
}
public void v(Object msg){
Log.v(this.tag, msg + "");
logger.info(msg);
}
……
public void e(Object msg,String srceenshot){
Log.e(this.tag, msg + "");
logger.error(msg);
takeScreenshot(srceenshot);
}
}
三、后话
至此整个测试框架就搭起来了,可能你还想将项目基于Jenkins构建个持续集成,那么你可以借助adb的命令来执行测试项目了:
adb shell am instrument -w -r -e debug false class com.alany.u2test.testcase.V1SanityTest com.alany.u2test/android.support.test.runner.AndroidJUnitRunner
可能你还想让手机不连USB数据线也可以跑,那么只需要build\outputs目录下将生成的apk安装到手机即可。
PS: 更多原创技术好文和资料,请关注下方公众号:“测试开发栈”公众号是由具有多年测试、开发经验的老兵们共同管理和运营,旨在分享原创测试、开发相关技术,包括但不限于:测试方向:Web自动化测试、移动端自动化测试、Web服务端测试、接口测试等;开发方向:Java开发、Android开发、前端开发等;
期望我们的经验和技术分享能让你每天都成长和进步,早日成为技术大牛~
欢迎大家分享和转发我们的文章(分享转发请保留文章出处),以便让更多的朋友关注我们,同时也欢迎加入我们的QQ群交流和提问:427020613