背景
appium自动化工作中,元素操作最常用的就是Id/xpath,因为【appium1.5.0后,不支持使用name定位】所有大家在工作中使用id/xpath定位;如果还是想用name定位,需要修改源码,具体大家自己去查,但在工作中id/xpath已经够用。
今天介绍目前我工作最常用的一些方法,希望能帮到大家,少走弯路。
TestNG常用注解
为什么要学习testng注解,因为在写测试类的时候需要,通过小小注解让他帮我们干活,所有需要先了解下:
TestNG简单介绍几种注解
注解 | 描述 |
---|---|
@BeforeSuite | 在该套件的所有测试都运行在注释的方法之前,仅运行一次 |
@AfterSuite | 在该套件的所有测试都运行在注释方法之后,仅运行一次 |
@BeforeClass | 在调用当前类的第一个测试方法之前运行,注释方法仅运行一次 |
@AfterClass | 在调用当前类的第一个测试方法之后运行,注释方法仅运行一次 |
@BeforeTest | 注释的方法将在属于test标签内的类的所有测试方法运行之前运行 |
@AfterTest | 注释的方法将在属于test标签内的类的所有测试方法运行之后运行 |
@BeforeGroups | 配置方法将在之前运行组列表。此方法保证在调用属于这些组中的任何一个的第一个测试方法之前不久运行 |
@AfterGroups | 此配置方法将在之后运行组列表。该方法保证在调用属于任何这些组的最后一个测试方法之后不久运行 |
@BeforeMethod | 注 释方法将在每个测试方法之前运行 |
@AfterMethod | 注释方法将在每个测试方法之后运行 |
@DataProvider | 标记一种方法来提供测试方法的数据。注释方法必须返回一个Object [] [],其中每个Object []可以被分配给测试方法的参数列表。要从该DataProvider接收数据的@Test方法需要使用与此注释名称相等的dataProvider名称 |
@Factory | 将一个方法标记为工厂,返回TestNG将被用作测试类的对象。该方法必须返回Object [] |
@Listeners | 定义测试类上的侦听器 |
@Parameters | 描述如何将参数传递给@Test方法 |
@Test | 将类或方法标记为测试的一部分,此标记若放在类上,则该类所有公共方法都将被作为测试方法 |
注意:
在使用@test注解用例的时候,最好使用T001做方法名称,这样test在跑的时候会根据0--1这样的开始执行。
如果想改变执行规则可以增加priority注解
@Test(description = "初始化登录启动", testName = "进入首页", priority = 0)
说明:
description:表示注释
testName:标志测试类
priority:表示执行顺序
实战
案例一
下载京东APP
启动app就能看到,每次启动都会提示这个,那么在写代码的时候咱们把这个方法:
类似这样的在写测试用例的时候可以这样写,之后其他类集成这个即可:
技巧二
如图:
类似中间这些应该怎么定位才最好,我们观察下面定位,可以采用xpath定位
代码示例
/**
* 点击购物车
*/
public void clickbaibao(AndroidDriver<AndroidElement> driver) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp("clickCart"), "百宝箱");
String[] name = {"京东超市", "数码电器", "京东服饰", "京东生鲜"};
for (int i = 0; i < name.length; i++) {
element = driver.findElement(By.xpath("//android.widget.TextView[@text='京东超市']".replace("京东超市", name[i])));
element.click();
}
}
点击进入京东超市后再判断是否登录成可以:
上可以采用id定位
代码示例
编写通用判断类
/**
* 统一判断是否通过
*
* @param driver 传driver
* @param elemn 定元素
* @param des 描述
*/
public void assertTrue(AndroidDriver<AndroidElement> driver, String elemn, String des) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp(elemn), des);
element = driver.findElement(getByLocator.getLocatorApp(elemn));
String text = element.getText();
if (text != null) {
Assert.assertTrue(true, des + "验证成功");
} else {
//如果失败系统会自动截图
Assert.fail("跳转失败");
}
}
完整代码
元素:
#点击首页clickCart=xpath>>//android.view.View[@content-desc='首页']#跳转成功assertTitile=id>>com.jingdong.app.mall:id/fd#退回home_back=id>>com.jingdong.app.mall:id/fe#百宝箱名字Jingdong_supermarket=xpath>>//android.widget.TextView[@text='京东超市']
代码示例
private GetByLocator getByLocator;
private WebElement element = null;
/**
* 构造函数
*/
public CartProvider() {
this.getByLocator = new GetByLocator("loginElement.properties");
}
/**
* 点击首页
*/
public void clickCart(AndroidDriver<AndroidElement> driver) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp("clickCart"), "点击首页");
element = driver.findElement(getByLocator.getLocatorApp("clickCart"));
element.click();
}
/**
* 点击百宝箱
* @param driver
*/
public void clickbaibao(AndroidDriver<AndroidElement> driver) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp("clickCart"), "百宝箱");
String[] name = {"京东超市", "数码电器", "京东服饰", "京东生鲜"};
for (int i = 0; i < name.length; i++) {
element = driver.findElement(getByLocator.getLocatorApp("Jingdong_supermarket".replace("京东超市", name[i])));
element.click();
//断言
assertTrue(driver, "assertTitile", name[i] + "跳转成功");
//退回
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp("home_back"), "退回");
driver.findElement(getByLocator.getLocatorApp("home_back"));
}
}
/**
* 统一判断是否通过
*
* @param driver 传driver
* @param elemn 定元素
* @param des 描述
*/
public void assertTrue(AndroidDriver<AndroidElement> driver, String elemn, String des) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp(elemn), des);
element = driver.findElement(getByLocator.getLocatorApp(elemn));
String text = element.getText();
if (text != null) {
Assert.assertTrue(true, des + "验证成功");
} else {
//如果失败系统会自动截图
Assert.fail("跳转失败");
}
}
测试类
import appout.appcase.data.CartProvider;
import org.testng.annotations.Test;
/**
* @author liwen
* @Title: CartTest
* @Description: 测试类
* @date 2019/11/23 / 19:57
*/
public class CartTest extends BestRuner {
CartProvider cartProvider = new CartProvider();
@Test(description = "点击首页百宝箱", testName = "点击百宝箱", priority = 1)
public void T002() {
cartProvider.clickHome(driver);
cartProvider.clickbaibao(driver);
}
}
xpath语法
https://www.w3school.com.cn/xpath/xpath_syntax.asp
遍历技巧二
观察如图:如果想遍历推荐分类每个商品应该怎么写?是每个写一个还是执行一个list之后挨个遍历?还是这么写?
观察定位方式:
在工作中我是这样写的
#分类categorylist=id>>com.jd.lib.category:id/a1z
代码
/**
* 分类写法
* @param driver
*/
public void categorylist(AndroidDriver<AndroidElement> driver) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp("categorylist"), "遍历分类");
//获取全部数据挨个遍历
List<AndroidElement> categorylist = driver.findElements(getByLocator.getLocatorApp("categorylist"));
for (int i = 0; i < categorylist.size(); i++) {
String text = categorylist.get(i).getText();
//输出遍历name
LogUtil.info(text);
categorylist.get(i).click();
}
}
属性判断写法
查看如下图:想知道该商品是否关注,应该这么写?
通过观察他的属性:
收藏属性
通过观察,代码写法:
1、获取该元素的地位
元素为:
#收藏productdetail=id>>com.jd.lib.productdetail:id/afr
简单代码
/**
* 收藏
*
* @param driver
*/
public void productdetail(AndroidDriver<AndroidElement> driver) {
WaitUtil.waitWebElement(driver, getByLocator.getLocatorApp("productdetail"), "收藏");
AndroidElement detail = driver.findElement(getByLocator.getLocatorApp("productdetail"));
String attribute = detail.getAttribute("selected");
if (attribute.equals(true)) {
LogUtil.info("目前商品收藏,目前的属性为:" + attribute);
} else {
LogUtil.info("商品没有收藏,目前的属性为:" + attribute);
}
}
通过得取属性就知道下一步怎么操作
总结
上面简单介绍几个测试用例写法,随着大家不断熟悉UI自动化,技能会逐渐增加,希望给大家带去一点帮助;
送大家一篇文章
庖丁解牛
先秦:庄周
吾生也有涯,而知也无涯 。以有涯随无涯,殆已!已而为知者,殆而已矣!为善无近名,为恶无近刑。缘督以为经,可以保身,可以全生,可以养亲,可以尽年。
庖丁为文惠君解牛,手之所触,肩之所倚,足之所履,膝之所踦[yǐ],砉[huā]然向然,奏刀騞[huō]然,莫不中音。合于《桑林》之舞,乃中《经首》之会。
文惠君曰:“嘻,善哉!技盖至此乎?”