测试服务,如果数据与业务放在一起看起来不是专业,把数据与业务分离是完全必要的,这也是市场常见的数据驱动框架,今天咱们就聊一聊怎么搭建自己数据驱动框架。
前置条件
Appium 环境搭建成功,不会参考自动化工具之 Appium 入门
文章,实在不会在参考网上怎么搭建。
主要实现 UI 自动化框架元素放文本存储、数据存储、代码直接存储等其实随便那个都行,只有自己用者方便就行,我工作中用文本文件存储,这样修改方便,脚本放 SVN/Git 管理就行,UI 自动元素操作基本常见的就是 ID/NAME/XPATH 等这几种,咱们写一个工具转换类即可。
元素读取工具类 /** * 移动端元素定位 * * @return * @param: name */ public By getLocatorApp(String name) { String locator = properties.getProperty(name.trim()); String locatorType = locator.split(">>")[0].toLowerCase(); String locatorValue = locator.split(">>")[1]; if (locatorType != null && locatorType != null) { logger.info("获取元素key: " + name + "\t 获取的定位类型:" + locatorType + "\t 获取的定位表达式: " + locatorValue); // 根据 locatorType 的变量值内容判断,返回何种定位方式的 By 对象 return getkeyVule(locatorType, locatorValue); } else { new RuntimeException("元素没有获取到!"); return null; } } /** * 读取元素 * @param locatorType * @param locatorValue * @return By */ public By getkeyVule(String locatorType, String locatorValue) { if ("id".equals(locatorType.toLowerCase())) { return By.id(locatorValue); } else if ("name".equals(locatorType.toLowerCase())) { return By.name(locatorValue); } else if (("classname".equals(locatorType.toLowerCase())) || ("class".equals(locatorType.toLowerCase()))) { return By.className(locatorValue); } else if (("tagname".equals(locatorType.toLowerCase())) || ("tag".equals(locatorType.toLowerCase()))) { return By.className(locatorValue); } else if (("linktext".equals(locatorType.toLowerCase())) || ("link".equals(locatorType.toLowerCase()))) { return By.linkText(locatorValue); } else if ("partiallinktext".equals(locatorType.toLowerCase())) { return By.partialLinkText(locatorValue); } else if (("cssselector".equals(locatorType.toLowerCase())) || ("css".equals(locatorType.toLowerCase()))) { return By.cssSelector(locatorValue); } else if ("xpath".equals(locatorType.toLowerCase())) { return By.xpath(locatorValue); } else { return By.tagName(locatorValue); } }
读取文件操作方法 public GetByLocator(String filename) { properties = new Properties(); try { FileInputStream in = new FileInputStream((sysProperty.getProperty("user.dir") + "/comsevenday/src/main/resources/uiElement/" + filename)); this.properties.load(in); in.close(); } catch (Exception e) { logger.info("找不到文件:" + filename); e.printStackTrace(); } }
编写元素存放位置:
内容为: #\u70B9\u51FB\u9996\u9875 clickCart=xpath>>//android.view.View[@content-desc='\u9996\u9875']
编写测试类 @Test public void ss() throws IOException { InputStream in = this.getClass().getResourceAsStream("/uielement/loginElement.properties"); Properties properties = new Properties(); properties.load(in); String to_shop_text1 = properties.getProperty("clickCart"); System.out.println(to_shop_text1); }
验证结果:
元素等待查找工具类 import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import org.openqa.selenium.By; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Reporter; /** * @author 7DGroup * @Title: WaitUtil * @Description: 等待查找元素工具类 * @date 2019/11/23 / 10:58 */ public class WaitUtil { public static void waitWebElement(AndroidDriver<AndroidElement> driver, By by, String name) { LogUtil.info("等待元素出现-->目前操步骤为:" + name); Reporter.log("目前操步骤为:" + name); WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.presenceOfElementLocated(by)); } }
元素定位类 package appout.appcase.data; import appout.utils.GetByLocator; import appout.utils.LogUtil; import appout.utils.WaitUtil; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.testng.Assert; import java.util.List; /** * @author 7DGroup * @Title: CartProvider * @Description: this is * @date 2019/11/23 / 10:57 */ public class CartProvider { private GetByLocator getByLocator; private WebElement element = null; /** * 构造函数 */ public CartProvider() { this.getByLocator = new GetByLocator("loginElement.properties"); } /** * 点击首页 */ public void clickHome(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 */ 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(); } } /** * 收藏 * * @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); } } /** * 统一判断是否通过 * * @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("跳转失败"); } } } // Assert.assertTrue("", "验证跳转成功"); // driver.findElement(By.id(""))
基础启动类 package appout.appcase; import appout.base.DriverBase; import appout.utils.LogUtil; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import org.openqa.selenium.By; import org.testng.Reporter; import org.testng.annotations.BeforeClass; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import java.util.concurrent.TimeUnit; /** * @author 7DGroup * @Title: LoginTest * @Description: 用例区域 * @date 2019/11/21 / 10:06 */ public class BestRuner { static AndroidDriver<AndroidElement> driver; public static AndroidDriver<AndroidElement> getDriver() { return driver; } /** * 初始化运行类 * * @param udid * @param port * @throws Exception */ @BeforeClass @Parameters({"udid", "port"}) public void BeforeClass(String udid, String port) { Reporter.log("步骤1:启动appium与应用", true); LogUtil.info("---这是设备ID号-->" + udid); LogUtil.info("--这是运行端口--->" + port); //通过路径获取包名与APP_ACTIVITY String apk = "com.jingdong.app.mall_70502.apk"; driver = DriverBase.initDriver(port, udid, apk, true); driver.manage().timeouts().implicitlyWait(80, TimeUnit.SECONDS); } @Test(description = "初始化登录启动", testName = "进入首页", priority = 0) public void T001() { LogUtil.info("启动"); driver.findElement(By.id("com.jingdong.app.mall:id/mj")).click(); } }
业务组合测试类 package appout.appcase; import appout.appcase.data.CartProvider; import org.testng.annotations.Test; /** * @author 7DGroup * @Title: CartTest * @Description: 测试类 extends BestRuner * @date 2019/11/23 / 19:57 */ public class CartTest { CartProvider cartProvider = new CartProvider(); @Test(description = "点击首页百宝箱", testName = "点击百宝箱", priority = 1) public void T002() { // cartProvider.clickHome(driver); // cartProvider.clickbaibao(driver); System.out.println("调试"); } }
其他测试类集成,即可。
总结 项目虽然小但包含了数据怎么存放,怎么获取,怎么换回成 selenium 识别的类型。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
权威发布,测试选择不纠结!第15届软件测试行业报告,直击行业发展,把握未来方向!