项目目录介绍
  • 目录结构如下:
    (包含:驱动的基础配置、全局异常处理、异常截图、报告自动生成、app常用操作方法封装、常用工具类封装)
    java版app自动化测试初始化模板-LMLPHP

  • 各包分层关系
    basepage包负责存放app公共操作方法、AndroidDriver基础配置、testNG公共执行顺序BaseTest,对外暴露驱动等。

  • BaseApp类包含app操作有:封装By类型的点击操作和输入框输入数据操作、切换到下一个窗口操作、上下左右滑动操作、具体坐标点击操作、直接使用adb命令的操作、前进后退刷新的操作等,其它方法可自行封住。

  • 部分封装方法如下:

 /**
     * 通过元素定位拿到 Element 元素对象
     *
     * @param locator By 类型元素定位
     * @return 定位到的元素
     */
    public WebElement locateElement(AndroidDriver driver,By locator) {
        try {
            wait = new WebDriverWait(driver, 10);
            return wait.until(ExpectedConditions.presenceOfElementLocated(locator));
        }catch (NoSuchElementException | TimeoutException e) {
            System.out.println("================当前页面未捕获该元素,继续执行用例==================");
        }
        return null;
    }
    /**
     * 点击元素
     * @param locator By 类型元素定位,做弹框或元素异常后接着往下执行
     * @return 点击的元素
     */
    public WebElement clickButton(AndroidDriver driver,By locator) {
        try {
            long time1 = DateUtils.getCurrentMillisecond();
            MobileElement buttonElement = (MobileElement) locateElement(driver,locator);
            wait.until(ExpectedConditions.elementToBeClickable(locator));
            if (buttonElement.isEnabled()){
                buttonElement.click();
                log.info("该点击事件耗时时间(ms):"+(DateUtils.getCurrentMillisecond()-time1));
                return buttonElement;
            }
        } catch (NoSuchElementException | TimeoutException e) {
            System.out.println("================当前页面未捕获该元素,截图保留>>>>继续执行用例==================");
            ScreenshotUtil.snapshot(driver);
        }
        return null;
//       System.out.println("改点击事件耗时时间(ms):"+(DateUtils.getCurrentMillisecond()-time1));
    }
    /**
     * 输入框输入数据
     * @param locator By 类型元素定位
     * @param content 输入的内容,支持多内容,可以键盘输入
     * @return 输入框元素
     */
    public WebElement sendInput(AndroidDriver driver,By locator, CharSequence... content) {
        WebElement inputElement = locateElement(driver,locator);
        inputElement.clear();
        inputElement.sendKeys(content);
        return inputElement;
    }
 /*=====================通过动作滑动==================================*/
    /**
     *向上滑动操作
     */
    public void swipeToUp(AndroidDriver driver) {
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        TouchAction action=new TouchAction(driver).press(PointOption.point(width/2, height*3/4)).waitAction(WaitOptions.waitOptions(duration))
                .moveTo(PointOption.point(width/2, height/4)).release();
        action.perform();
    }
    /**
     *向下滑动操作
     */
    public void swipeToDown(AndroidDriver driver) {
        int height = driver.manage().window().getSize().height;
        int width = driver.manage().window().getSize().width;
        TouchAction action=new TouchAction(driver).press(PointOption.point(width/2, height/4)).waitAction(WaitOptions.waitOptions(duration))
                .moveTo(PointOption.point(width/2, height*3/4)).release();
        action.perform();
    }
    /**
     *向左滑动操作
     */
    public void swipeToLeft(AndroidDriver driver) {
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        TouchAction action=new TouchAction(driver).press(PointOption.point(width*3/4, height/2)).waitAction(WaitOptions.waitOptions(duration))
                .moveTo(PointOption.point(width/4,height/2)).release();
        action.perform();
    }
    /**
     *向右滑动操作
     */
    public void swipeToRight(AndroidDriver driver) {
        int width = driver.manage().window().getSize().width;
        int height = driver.manage().window().getSize().height;
        TouchAction action=new TouchAction(driver).press(PointOption.point(width / 4, height / 2)).waitAction(WaitOptions.waitOptions(duration))
                .moveTo(PointOption.point(width*3/4,height/2)).release();
        action.perform();
    }

    /*=====================通过具体坐标点击操作,appium&&adb两种方式==================================*/
    /**
     * 通过具体坐标点击
     */
    public void taptest(AndroidDriver driver,int x, int y){
        /**设置显示等待时间10s  driver=baseAndroidDriver.getDriver(baseConfig)
        特注:显示等待与隐式等待相对,显示等待必须在每一个需要等待的元素前面进行声明,如果在规定的时间内找到元素,则直接执行,即找到元素就执行相关操作
         */
        wait = new WebDriverWait(driver,5);
        //tap点击坐标,输入坐标,然后再release()释放坐标点,用perform()去执行一系列action操作
        action = new TouchAction(driver).tap(PointOption.point(x,y)).release().perform();

    }
    /**
     * 通过adb命令驱动被测设备
     */
    public void adbInput(AndroidDriver driver ,String input){
        try {
            Process process = Runtime.getRuntime().exec(input);
            wait = new WebDriverWait(driver,5);
            process.destroy();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • page包(通用PO模式):分为data数据包和element元素操作包,把定位元素和输入框数据统一放到data包中,元素的操作放到element包中。其中元素的操作数据来源于data包中。
    java版app自动化测试初始化模板-LMLPHP

  • testcase包是根据业务流程编写用例步骤(后面的用例维护均在此包下)
    java版app自动化测试初始化模板-LMLPHP

  • resource包下可以放chromedriver驱动或者存放异常捕获的截图、测试报告自动生成index.html报告(由于使用springboot可以直接访问报告)另一种测试报告用的最多的是allure2,一个开源很好的报告模板allure2 的GitHub地址测试报告输出到allure-results包下。
    java版app自动化测试初始化模板-LMLPHP

  • allure2报告集成,win下需要先下载allure2的zip包GitHub官网下载地址allure2,下载zip包后需要配置下环境变量,用例执行完成后会生成allure-results文件夹,在当前文件夹下执行

allure serve allure-results

即可自动打开web测试报告,如下:
java版app自动化测试初始化模板-LMLPHP

模板流程说明
  • 1、先在testcase包内写测试用例流程,testcase包下的类需要继承BaseTest 来获取driver驱动
    eg:
public class YynCases extends BaseTest {
    /**
     * 测试示例用例,继承BaseTest获取driver驱动
     * 操作层
     */
    EnterYynElemnt enterMiniElemnt = new EnterYynElemnt();
    public void getDriverCase(){
        System.out.println(driver);
       //点击弹框按钮
        enterMiniElemnt.popupClick(driver);
    }
}
  • 2、创建page包下的element包中的元素操作类,即:EnterYynElemnt 类此包下的类需要继承BaseApp类来获取封装的公共操作方法。
@Slf4j
public class EnterYynElemnt extends BaseApp{
    /**
     * 继承BaseApp使用公共封装方法
     * */
    //点击弹框
    public void popupClick(AndroidDriver driver) {
        //使用封装By类型元素定位,且数据和元素分离
        log.info("点击弹框");
        clickButton( driver, PopupData.POPUP1);
    }
}
  • 3、创建page包下的data包的定位数据或者是输入框数据,所有的元素定位和输入数据均在此包下维护。上面参数POPUP1通过id定位,PopupData类下的POPUP1数据如下:
public class PopupData {
    //升级弹框
    public static final By POPUP1= By.id("com.tengyun.yyn:id/layout_confirm_cancel");
    //第二个弹框
    public static final By POPUP2 = By.id("com.tengyun.yyn:id/layout_activity_cancel");
  • 4、其中第二步使用的是BaseApp封装的公共类方法clickButton
 public WebElement clickButton(AndroidDriver driver,By locator) {
        try {
            long time1 = DateUtils.getCurrentMillisecond();
            MobileElement buttonElement = (MobileElement) locateElement(driver,locator);
            wait.until(ExpectedConditions.elementToBeClickable(locator));
            if (buttonElement.isEnabled()){
                buttonElement.click();
                log.info("该点击事件耗时时间(ms):"+(DateUtils.getCurrentMillisecond()-time1));
                return buttonElement;
            }
        } catch (NoSuchElementException | TimeoutException e) {
            System.out.println("================当前页面未捕获该元素,截图保留>>>>继续执行用例==================");
            ScreenshotUtil.snapshot(driver);
        }
        return null;
//       System.out.println("改点击事件耗时时间(ms):"+(DateUtils.getCurrentMillisecond()-time1));
    }

输入框输入数据方法也是很常用的

    public WebElement sendInput(AndroidDriver driver,By locator, CharSequence... content) {
        WebElement inputElement = locateElement(driver,locator);
        inputElement.clear();
        inputElement.sendKeys(content);
        return inputElement;
    }
  • 5、最后可以统一把testcase包下的类放到testNG的入口中执行测试并生成报告(由于使用springboot框架没有用testNG的xml配置,而是通过封装方法进行配置)
/**
 * 测试用例总入口
 * */
   @Test
    public void runCases(){
        //执行测试用例入口
        BaseTestngInit baseTestngInit = new BaseTestngInit();
        baseTestngInit.baseTestngInitCode();
    }

testNG封装的工具类BaseTestngInit(工具类中也可以通过testng.xml初始化testng,具体看个人使用习惯)

 /**
     * 初始化testng
     */
    public  void baseTestngInitCode()  {
        //创建testng对象
        TestNG testng = new TestNG();
        //创建报告监听器对象
        ExtentTestNGIReporterListener reportListener = new ExtentTestNGIReporterListener();
//        TestLogListener testLogListener = new TestLogListener();
        //设置需要执行的测试用例类
        testng.setTestClasses(new Class[] { com.iappium.testcase.YynCases.class});
        //添加监听器
        testng.addListener(reportListener);
//        testng.addListener(testLogListener);
        //运行测试
        testng.run();
    }

点击可获取该项目源码地址

  • 更多测试技术分享、学习资源以及一些其他福利可关注公众号:【Coding测试】获取:

java版app自动化测试初始化模板-LMLPHP

09-29 00:37