基于Appium+java进行Android自动化测试:列表定位、用例失败截图、长按、滑动、依赖、切换~
一、appium中对元素的定位方法的使用
场景:元素的定位,常利用resource-id、index、name(text)等属性进行定位。如下图所示,列表项目的index、resource-id、class、package等属性均相同,无法利用常用属性进行区分。直接根据resource-id、index等属性,由于列表中全部相同,默认自动选择的是第一个元素。故对元素定位进行了调研,可以通过此类方法获取当前页面的任意一个元素;
方法:用通用属性获取所有该类型的当前页面的某个目标元素,示例:
(1)获取text为“备注”的所有元素
List bookMarkList = findList(“备注”);
(2)获取当前列表页面中所有项目数:
int itemNum = bookMarkList.size();
(3)获取当前列表中第一个元素
WebEelement targetEle = bookMarkList.get(0);
示例
/*resource-id、text、index无法区分时获取列表,使用的时候,调用此方法即可*/
publicstaticList<WebElement> findList(String name){
List<WebElement> BookMarkList = elements(By.name(name));
returnBookMarkList;
}
publicstaticList<WebElement> findListByid(String id){
List<WebElement> BookMarkList = elements(By.id(id));
returnBookMarkList;
}
获取列表方法调用(From Appium demo source code,所有TestCase的基类)
/**
* Return a list of elements by locator *
*/
publicstaticList<WebElement> elements(By locator){
returndriver.findElements(locator);
}
二、用例失败截图
场景:我们进行自动化测试过程中,需要对一些用例结果进行截图或者对错误的case进行记录,可以通过截屏来分析失败或者异常原因,保存场景。
//调用方法
getScreenshotAs ();
//截屏并保存至本地
publicstaticvoidtakeScreenShots(AndroidDriver driver)
{
File screenShotFile = driver.getScreenshotAs(OutputType.FILE);
try{
FileUtils.copyFile(screenShotFile, newFile( "D:AutoScreenCapture' + System.currentTimeMillis() +'.jpg"));
}
catch(IOException e) {e.printStackTrace();}
}
注:静态方法System.currentTimeMillis()返回1970-01-01 00:00:00.000到现在的毫秒数,返回值是一个long型;
三、依赖测试
场景:如果测试用例间有依赖性,也就是如果想执行B,就必须要先执行A。可以利用TestNG中依赖测试方法解决。如自动化测试有些测试用例都依赖于同类型的操作,作为基础条件。地图自动化测试中,收藏模块很多添加收藏的,调研后利用方法的依赖。
依赖规则:
method2()依赖于method1()
If method1() is passed, method2() will be executed.
If method1() is failed, method2() will be skipped.
示例:
@Test
publicvoidmethod1()
{
BookMarkEditPage bookMarkPageEdit = newBookMarkEditPage();
bookMarkPageEdit.addPoiToBookMark( "清华东路西口");
Assert.assertTrue(bookMarkPageEdit.verifyAddPoiToBookMark( "清华东路西口"), "添加poi点失败");
System.out.println( "This is method 1");
}
@Test(dependsOnMethods = { "method1"})
publicvoidmethod2(){
BookMarkCommonPage bookMarkCommonPage = newBookMarkCommonPage();
bookMarkCommonPage.deleteAllItems(); Assert.assertTrue(bookMarkCommonPage.isDisplayed( "你还没有添加收藏"), "删除失败!");
System.out.println( "This is method 2");
四、Android–模拟长按操作
场景:自动化测试过程中需要模拟用户进行点击、长按、滑动等不同操作。
方法:对元素进行定位,TouchAction,然后设置一个等待时间,进行模拟。
publicstaticAndroidDriver driver;
/*长按操作:waitAction的参数单位是ms*/
publicstaticvoidlongClick(String id){
WebElement longClick = driver.findElement(By.id(id));
newTouchAction(driver).longPress(longClick).waitAction( 1000).perform();
}
/*TouchAction.class中定义*/
publicTouchAction waitAction(intms){
TouchAction.ActionParameter action = newTouchAction.ActionParameter( "wait");
action.addParameter( "ms", Integer.valueOf(ms));
this.parameterBuilder.add(action);
returnthis;
}
五、模拟上下、左右滑动操作
场景:项目自动化测试中,有滑动底图、滑动列表的场景需求。
方法:获取当前屏幕的size,设置滑动的起终点坐标,调用swip()方法。
/**
* 滑动操作,可以用来模拟左右,上下滑动操作
* @paramstartX 起点的x坐标
* @paramstartY 起点的y坐标
* @paramendX 终点的x坐标
* @paramendY 终点的y坐标
* @paramduration 单位是秒
*/
publicstaticvoidswipe(intstartX, intstartY, intendX, intendY, intduration){
driver.swipe(startX, startY, endX, endY, duration* 1000);
}
/**
* 获取手机屏幕的size
* @return
*/
publicstaticDimension getScreenSize(){
returndriver.manage().window().getSize();
}
//向上滑动
publicstaticvoidswipeToUp(intduration){
intwidth = driver.manage().window().getSize().width;
intheight = driver.manage().window().getSize().height;
driver.swipe(width/ 2, height/ 2, width/ 2, height/ 4, duration* 1000);
}
//向下滑动
publicstaticvoidswipeToDown(intduration){
intwidth = driver.manage().window().getSize().width;
intheight = driver.manage().window().getSize().height;
driver.swipe(width/ 2, height/ 4, width/ 2, height/ 2, duration* 1000);
}
//向左滑动
publicstaticvoidswipeToLeft(intduration){
intwidth = driver.manage().window().getSize().width;
intheight = driver.manage().window().getSize().height;
driver.swipe(width* 3/ 4, height/ 2, width/ 4, height/ 2, duration* 1000);
}
//向右滑动
publicstaticvoidswipeToRight(intduration){
intwidth = driver.manage().window().getSize().width;
intheight = driver.manage().window().getSize().height;
driver.swipe(width/ 4, height/ 2, width* 3/ 4, height/ 2, duration* 1000);
}
六、native app、webview切换
场景:项目测试中,有app、web页切换的场景需求,比如搜索结果餐饮团购详情页、第三方微博登录页等。
方法:可以通过切换context实现Native app 和Webview切换。
/**
* 从native app切换到webview
* 注意:Appium官网有提到,4.3以上才支持在android模式下切换到webview,如果是之前的版本, 需要使用selendroid模式
* @return返回是否支持切换到webview
*/
publicstaticbooleanswitchToWebView(){
Set<String> contextNames = driver.getContextHandles();
System.out.println(contextNames.toArray());
for(String contextName : contextNames) {
if(contextName.contains( "WEBVIEW_com.sogou.map.android.maps")) {
driver.context( "WEBVIEW_com.sogou.map.android.maps");
returntrue;
}
}
returnfalse;
}
/*从webview切换到native app*/
publicstaticvoidswitchToNativeApp(){
Set<String> contextNames = driver.getContextHandles();
driver.context( "NATIVE_APP");
}
/*通过xpath来查找元素,用于WebView内的测试*/
publicstaticWebElement findByXpathInWebView(String attrName){
//return driver.findElement(By.xpath("//a[@log='" + attrName + "'] | //div[@log='" + attrName + "']"));
returndriver.findElement(By.xpath( "//*[@log='"+ attrName + "']"));
}