• 基于APPIUM测试微信公众号的UI自动化测试框架


    框架初衷

    前两周组内的小伙伴跟我说她现在测试的微信公众号项目(保险)每次上新产品时测试起来很费时,存在大量的重复操作(点点点),手工测试每个产品可能需要半天到一天的时间,复杂的产品需要两天。
    由于保险下单的过程中字段比较多,输入费劲的同时测试用例也很多(不同年龄段、工种、有无社保等),且!每个产品的页面都有部分差异!
    问我能否基于UI自动化提高她测试新产品的测试速度,同时用于上线时生产的验证。
    因为我写过微信公众号页面的UI监控脚本,也尝试过基于appium的多机并发测试,于是我就想,能否搭建一个框架,让小伙伴每次测试新产品的时候只要输入测试数据+修改产品差异部分代码,然后框架分发给不同的手机去执行,最后展示测试报告?

    最终效果

    一个case大约3-5分钟,三台手机执行测话三个新产品半天就能测完。
    下面是放到jenkins上运行demo的测试报告。


     
     

    下面是用例运行失败时的界面,提供截图、重试、case日志以及appium的日志。


     
     

    框架介绍

    1.主要工具

    JAVA 版本1.8
    appium-server 版本1.6.3
    appium java-client 版本5.0.0-BETA8
    testNG 用例组织
    Allure2 测试报告
    Jenkins 持续集成
    Git 代码管理

    2.工程目录及主要代码

     
     

    pages:没有采用PO模式,页面以接口的形式定义,页面元素即为变量。
    pageoptions:页面功能封装在pageoptions包中,封装成静态方法。
    testcase:继承BaseDriver,driver初始化后即可执行测试。
    util:appiumserver启动工具类、失败自动截图等

    下面是每个package内的代码。

    2.1 POM.XML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.cpeoc</groupId>
        <artifactId>jyx</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    
        <name>jyx</name>
    
        <properties>
            <java.version>1.7</java.version>
            <aspectj.version>1.8.10</aspectj.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>6.11</version>
            </dependency>
            <dependency>
                <groupId>io.appium</groupId>
                <artifactId>java-client</artifactId>
                <version>5.0.0-BETA8</version>
            </dependency>
    
            <dependency>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-testng</artifactId>
                <version>2.0-BETA14</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.hamcrest</groupId>
                <artifactId>hamcrest-all</artifactId>
                <version>1.3</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
                <version>1.7.21</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>1.6.1</version>
            </dependency>
            <dependency>
                <groupId>com.belerweb</groupId>
                <artifactId>pinyin4j</artifactId>
                <version>2.5.1</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.3</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.18.1</version>
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                        <argLine>
                            -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                        </argLine>
                        <suiteXmlFiles>
                            <suiteXmlFile>testng-OnePhone.xml</suiteXmlFile>
                        </suiteXmlFiles>
                        <!-- <workingDirectory>target</workingDirectory> -->
                    </configuration>
                    <dependencies>
                        <dependency>
                            <groupId>org.aspectj</groupId>
                            <artifactId>aspectjweaver</artifactId>
                            <version>${aspectj.version}</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    2.2pageoptions包

    package com.cpeoc.jyx.pageoptions;
    
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.ui.WebDriverWait;
    import org.testng.Assert;
    
    import com.cpeoc.jyx.pages.Index;
    import com.cpeoc.jyx.util.PinYinUtil;
    import com.cpeoc.jyx.util.WaitUtil;
    
    import io.appium.java_client.AppiumDriver;
    
    /**
     * 首页通用功能实现类
     * @author ken
     * @date 2018年6月15日
     */
    public class IndexOp {
        /**
         * 切换到指定城市
         * @param driver
         * @param wait
         * @param cityName 城市名
         */
        public static void switchCity(AppiumDriver<WebElement> driver,WebDriverWait wait,String cityName){
            
            String firstWordtOfCity = PinYinUtil.getFirstWordFromChinese(cityName);
            String cityNameXpath = "//*[contains(text(),'"+cityName+"')]";
            String cityPinYinXpath = "//*[contains(text(),'"+firstWordtOfCity+"')]";
            WaitUtil.waitElementByXpath(wait, Index.LOCATE).click();
            WaitUtil.waitElementByXpath(wait, cityPinYinXpath).click();
            WaitUtil.waitElementByXpath(wait, cityNameXpath).click();
            WebElement locate = WaitUtil.waitElementByXpath(wait, Index.LOCATE);
            Assert.assertEquals(locate.getText(), cityName, "城市切换有bug!");
            
        }
        
    }
    
    

    2.3pages包

    package com.cpeoc.jyx.pages;
    /**
     * 简易险首页
     * @author ken
     * @date 2018年6月8日
     * @see 
     *  首页用到的元素全部定义在这里,用xpath保存
     */
    public interface Index {
        
        /**
         * 全国站切换确认窗口
         */
        String ALERT_BTN = "//*[@class='alert-btn']";
        
        /**
         * 定位城市
         */
        String LOCATE = "//*[contains(@class,'locate')]";
        
        /**
         * 意外险
         */
        String  ACCIDENT ="//a[contains(@href,'categoryCode=1000')]";
        
        /**
         * 健康险
         */
        String  HEALTH ="//a[contains(@href,'categoryCode=1300')]";
        
        /**
         * 财产险
         */
        String  PROPERTY ="//a[contains(@href,'categoryCode=1200')]";
        
        /**
         * 旅游险
         */
        String  TOURISM ="//a[contains(@href,'categoryCode=1100')]";
        
        /**
         * 航空险
         */
        String  AVIATION ="//a[contains(@href,'categoryCode=1103')]";
    
    }
    
    

    2.4testcase包

    一个简单case。

    package com.cpeoc.jyx.testcases.index;
    
    import io.qameta.allure.Description;
    import io.qameta.allure.Epic;
    
    import org.testng.annotations.Test;
    
    import com.cpeoc.jyx.pageoptions.IndexOp;
    import com.cpeoc.jyx.util.BaseDriver;
    
    /**
     * 城市定位 -- 切换
     * 
     * @author ken
     * @date 2018年6月12日
     * @see 测试微信号:王九 东莞切换到重庆 分组:wangjiu
     */
    @Epic("城市定位")
    public class TestCitySelect extends BaseDriver {
    
        @Test(groups = { "wangjiu" })
        @Description("测试城市切换")
        public void testCitySelect() {
            System.out.println("运行测试用例------------------TestCitySelect");
            // 1.点击城市进入城市选择页。点击C-重庆市
            IndexOp.switchCity(driver, wait, "重庆市");
    
        }
    
    }
    
    

    产品下单case。

    package com.cpeoc.jyx.testcases.insbuy;
    
    
    import io.qameta.allure.Description;
    import io.qameta.allure.Epic;
    import io.qameta.allure.Story;
    
    import org.openqa.selenium.WebElement;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Test;
    
    import com.cpeoc.jyx.pageoptions.CommonPageOp;
    import com.cpeoc.jyx.pageoptions.IndexOp;
    import com.cpeoc.jyx.pages.BaiWanAnXinLiao;
    import com.cpeoc.jyx.pages.Common;
    import com.cpeoc.jyx.util.BaseDriver;
    import com.cpeoc.jyx.util.WaitUtil;
    
    /**
     * 百万安心疗-重庆
     * @author ken
     * @date 2018年6月14日
     */
    

    2.5util包

    失败自动截图。

    package com.cpeoc.jyx.util;
    
    import io.appium.java_client.AppiumDriver;
    import io.qameta.allure.Attachment;
    
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.WebElement;
    import org.testng.IHookCallBack;
    import org.testng.IHookable;
    import org.testng.ITestResult;
    /**
     * 失败自动截图监听类
     * @author ken
     * @date 2018年6月21日
     * @see
     *  继承testng的接口
     *  使用Allure附件注解
     */
    public class AllureReporterListener implements IHookable {
    
        @Override
        public void run(IHookCallBack callBack, ITestResult testResult) {
            callBack.runTestMethod(testResult);
            if (testResult.getThrowable() != null) {
                try {
                    //takeScreenShot(testResult.getMethod().getMethodName());
                    takeScreenShotA(testResult);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Attachment(value = "失败截图", type = "image/png")
        private byte[] takeScreenShotA( ITestResult testResult) throws Exception {
            System.out.println("-----------监听到用例运行失败,截图------------");
            BaseDriver b = (BaseDriver) testResult.getInstance();
            AppiumDriver<WebElement> driver = b.getDriver();
            driver.context(Config.NATIVE_CONTEXT);
            System.out.println("-----------切换context到NATIVE_APP---------");
            return driver.getScreenshotAs(OutputType.BYTES);
        }
    
    }
    
    

    2.6testng.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    
    <suite name="简易险测试用例集" parallel="tests">
        <listeners>
            <listener class-name="com.cpeoc.jyx.util.AllureReporterListener"/>
        </listeners>
        
        <test name="wangjiu">
            <!-- 这里是手机信息 -->
            <parameter name="deviceName" value="28a38e6f" />
            <parameter name="platformVersion" value="5.1" />
            <!-- 这里是要调试的测试类  -->
            <classes>
                <class name="com.cpeoc.jyx.testcases.index.TestCitySelect" />
                <class name="com.cpeoc.jyx.testcases.index.TestCityDG" />
                <class name="com.cpeoc.jyx.testcases.insBuy.TestBaiWanAnXinLiao"/>
            </classes>  
        </test>
        <test name="miaomiao">
            <!-- 这里是手机信息 -->
            <parameter name="deviceName" value="fe3123d2" />
            <parameter name="platformVersion" value="7.0" />
            <!-- 这里是要调试的测试类 --> 
            <classes>
                <class name="com.cpeoc.jyx.testcases.index.TestCityQG" />
                <class name="com.cpeoc.jyx.testcases.insBuy.TestBaiWanAnXinLiao"/>      
            </classes>  
        </test>
    </suite>
    
    

    最后

    当然,里边还有很多具体的业务和代码实现没有介绍,只是给有需要的同学一点借鉴,欢迎交流。

     转:https://www.jianshu.com/p/87f0b13dbfd1
  • 相关阅读:
    Atitit 经济学常见的流派 古典主义与凯恩斯主义
    Atitit 学习方法 体系化学习方法 Excel 科目,分类,专业 三级分类。。 知识点。。 课程就是每一个知识点的详细化。。 比如经济学 类别 专业 xx概论知识点 3、金
    atiitt it学科体系化 体系树与知识点概念大总结.xlsx
    Atitit 减少财政支出普通人如何蹭政府补贴措施 attilax大总结.docx
    Atitit 信用管理概论 attilax学习心得
    Atitit.月度计划日程表 每月流程表v5
    Atitit 企业6大职能 attilax总结
    Atitit 常见每日流程日程日常工作.docx v8 ver ampm imp 签到 am y 天气情况检查 am y 晨会,每天或者隔天 am 每日计划(项目计划,日计划等。 am
    Atitit 财政赤字解决方案
    Atitit 建设自己的财政体系 attilax总结 1.1. 收入理论 2 1.2. 收入分类 2 1.3. 2 1.4. 非货币收入 2 1.5. 2 1.6. 降低期望 2 1.7.
  • 原文地址:https://www.cnblogs.com/kaola8023/p/14500069.html
Copyright © 2020-2023  润新知