zoukankan      html  css  js  c++  java
  • java版app自动化测试初始化模板

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

    • 各包分层关系
      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包中。
      image.png

    • testcase包是根据业务流程编写用例步骤(后面的用例维护均在此包下)

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

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

    allure serve allure-results
    

    即可自动打开web测试报告,如下:

    模板流程说明
    • 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测试】获取:
    Coding测试

    记录工作中使用的CI/CD流程
  • 相关阅读:
    hihoCoder#1128 二分·二分查找
    hihoCoder#1127 二分图三·二分图最小点覆盖和最大独立集
    hihoCoder#1122 二分图二•二分图最大匹配之匈牙利算法
    hihoCoder#1105 题外话·堆
    Ajax详细剖析
    web框架之--Tornado
    web框架之--先来个介绍
    前端之--Jquery-玩穿它!
    前端之--DOM详解应用
    前端之--JavaScript作用域--超细讲解
  • 原文地址:https://www.cnblogs.com/CodingTest/p/13744480.html
Copyright © 2011-2022 走看看