JavaApp自动化测试系列[v1.0.0][Appium关键字驱动测试框架]

关键字驱动也称为表格驱动或者操作名驱动,通常将测试用例拆分为5类关键字部分包括:测试步骤,测试对象,测试对象的动作,测试数据,测试结果

AppTestFrameworkKT/
|----src/main/java/
	|----com.davieyang.base/
		|----BaseActivity.java
	|----com.davieyang.util/
		|----DataProviderFromExcel.java
		|----Constants.java
		|----FindElement.java
		|----Action.java
|----src/test/java/
	|----com.davieyang.testScripts/
		|----TestRegister.java
|----data/
	|----register.xlsx
|----result/
|----config/
	|----log4j.properties
|----pom.xml
|----testng.xml

Constants提取Desired Capabilities

package com.davieyang.util;

public class Constants {
    public class mobile_RedMi_3{
        public static final String deviceName = "RedMi 3";
        public static final String udid = "claeae297d72";
        public static final String platformVersion = "5.1.1";
        public static final String platformName = "Android";
        public static final String appPackage = "io.selendroid.testapp";
        public static final String appActivity = ".HomeScreenActivity";
        public static final String unicodeKeyboard = "True";
        public static final String noSign = "True";
    }
}

BaseActivity公共类

package com.davieyang.base;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import java.net.URL;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import com.davieyang.util.Constants;


public class BaseActivity {
    public static Logger log = Logger.getLogger(BaseActivity.class.getName());
    public static AndroidDriver<AndroidElement> driver;
    @BeforeClass
    public void setUp() throws Exception{
        PropertyConfigurator.configure("config/log4j.properties");
        log.info("--------测试用例执行--------");
        DesiredCapabilities cap = new DesiredCapabilities();
        cap.setCapability("deviceName", Constants.mobile_RedMi_3.deviceName);
        cap.setCapability("udid", Constants.mobile_RedMi_3.udid);
        cap.setCapability("platformVersion", Constants.mobile_RedMi_3.platformVersion);
        cap.setCapability("platformName", Constants.mobile_RedMi_3.platformName);
        cap.setCapability("appPackage", Constants.mobile_RedMi_3.appPackage);
        cap.setCapability("appActivity", Constants.mobile_RedMi_3.appActivity);
        cap.setCapability("unicodeKeyboard", Constants.mobile_RedMi_3.unicodeKeyboard);
        cap.setCapability("noSign", Constants.mobile_RedMi_3.noSign);
        driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), cap);


    }
    @AfterClass
    public void endTest(){
        log.info("--------测试用例执行结束--------");
        driver.quit();
    }

    public AndroidDriver<AndroidElement> getDriver() {
        return driver;
    }
}

关键字驱动

配置pom

        <!--处理Excel2003及以下版本 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <!--处理Excel2007及以上版本 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

在data文件夹内新建register.xlsx文件,并修改第一个Sheet的名字为“测试任务调度”并写入如下内容

testCaseName testCaseDetail isRun result
register 注册全过程 yes

然后创建第二个Sheet及“测试用例”页用于存放具体测试用例

testCaseID testStepID testStepDetail objectName inspector actionStep data result
register1 testStep1 点击注册文件夹 首页-注册 io.selendroid.testapp:id/startUserRegistration click null

解析该Excel文件工具类

package com.davieyang.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


public class DataProviderFromExcel {
    private static File file = null;
    private static XSSFWorkbook xssfWorkbook = null;
    private static XSSFSheet xssfSheet = null;
    private static XSSFRow xssfRow = null;
    private static XSSFCell xssfCell = null;


    /**
     * 初始化Excel文档,设定待操作的文件路径和Sheet
     */
    public static void getExcel(String filePath) throws Exception{
        file = new File(filePath);
        FileInputStream inputStream = new FileInputStream(file);
        xssfWorkbook = new XSSFWorkbook(inputStream);
        if(xssfWorkbook == null){
            throw new Exception("Excel为空");
        }
    }

    /**
     * 读取指定单元格的值
     */
    public static String getCellData(String sheetName, int rowNum, int colNum) throws Exception{
        xssfSheet = xssfWorkbook.getSheet(sheetName);
        try{
            xssfCell = xssfSheet.getRow(rowNum).getCell(colNum);
            String cellData = getCellValue(xssfCell);
            return cellData;
        }catch (Exception e){
            return "";
        }
    }

    /**
     * 根据Excel中格式的不同来读取不同格式的值
     */
    private static String getCellValue(XSSFCell cell){
        String strCell = "";
        if(cell.getCellTypeEnum() == CellType.STRING){
            strCell = cell.getStringCellValue();
        }
        else if(cell.getCellTypeEnum() == CellType.NUMERIC){
            strCell = String.valueOf(cell.getNumericCellValue());
            strCell = strCell.split(".")[0];
        }
        else if(cell.getCellTypeEnum() == CellType.BOOLEAN){
            strCell = String.valueOf(cell.getBooleanCellValue());
        }
        else if(cell.getCellTypeEnum() == CellType.BLANK);{
            strCell = "";
        }
        return strCell;
    }

    /**
     * 向指定的单元格写入数据
     */
    public static void setCellData(int rowNum, int colNum, boolean result, String sheetName,
                                   String filePath) throws Exception{
        xssfSheet = xssfWorkbook.getSheet(sheetName);
        try{
            xssfRow = xssfSheet.getRow(rowNum);
            xssfCell = xssfRow.getCell(colNum);
            if(xssfCell == null){
                xssfCell = xssfRow.createCell(colNum);
                xssfCell.setCellValue(result);
            }else {
                xssfCell.setCellValue(result);
            }
            FileOutputStream outputStream = new FileOutputStream(filePath);
            xssfWorkbook.write(outputStream);
            outputStream.close();
        }catch (Exception e){
            throw e;
        }
    }

    /**
     * 获取指定Sheet的单元格行数
     */
    public static int getAllRowNum(String sheetName){
        xssfSheet = xssfWorkbook.getSheet(sheetName);
        return xssfSheet.getLastRowNum();
    }

}

页面元素封装

package com.davieyang.util;
import org.apache.log4j.Logger;
import com.davieyang.testScripts.TestRegister;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;


public class FindElement {
    static Logger log = Logger.getLogger(FindElement.class.getName());
    public static AndroidElement findElementbyType(AndroidDriver<?> driver, String controllerInfo) throws Exception{
        MobileElement element = null;
        if(controllerInfo.startsWith("//")){
            element = (MobileElement) driver.findElementByXPath(controllerInfo);
        }
        else if(controllerInfo.contains(":id/")){
            element = (MobileElement) driver.findElementById(controllerInfo);
        }else {
            try{
                element = (MobileElement) driver.findElementByAndroidUIAutomator("text(\""+controllerInfo+"\")");
            }catch (Exception e){
                element = (MobileElement) driver.findElementByClassName(controllerInfo);
            }
        }
        return (AndroidElement) element;
    }

    public static MobileElement findElement(AndroidDriver<?> driver, String controllerInfo) throws Exception{
        int elementInspectCount, elementInspectInterval;
        elementInspectCount = Constants.controllerInPage.elementInspectCount;
        elementInspectInterval = Constants.controllerInPage.elementInspectInterval;
        MobileElement element = null;
        for(int i=0; i<elementInspectCount;i++){
            Thread.sleep(elementInspectInterval);
            try{
                element = findElementbyType(driver, controllerInfo);
                log.info("已经找到元素对象");
                return element;
            }catch (Exception e){
                log.info("控件未找到,Waiting......");
                continue;
            }
        }
        log.info("多次查找未找到元素控件,测试结果位设为false");
        TestRegister.testResult = false;
        throw new IllegalArgumentException("指定时间内未找到页面空间对象");
    }
}

工具类封装

package com.davieyang.util;

import io.appium.java_client.MobileElement;
import com.davieyang.testScripts.TestRegister;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import io.appium.java_client.android.AndroidKeyCode;
import org.apache.log4j.Logger;



public class Action {
    static Logger log = Logger.getLogger(Action.class.getName());
    private static AndroidDriver<AndroidElement> driver;
    public Action(AndroidDriver<AndroidElement> driver){
        this.driver =driver;
    }
    /**
     * 实现单击操作
     * @param mobileElement 页面对象
     * @param data 无任何意义,只为代码一致性
     */
    public void click(MobileElement mobileElement, String data){
        try{
            mobileElement.click();
        }catch (Exception e){
            try{
                Thread.sleep(Constants.controllerInPage.elementInspectInterval);
            }catch (InterruptedException e1){
                TestRegister.testResult = false;
                e1.printStackTrace();
            }
            mobileElement.click();
        }
    }

    /**
     * 单击单击框,单击前判断是否已经处于选择状态
     * @param mobileElement
     * @param data
     */
    public void click_radio(MobileElement mobileElement, String data){
        try{
            if(data.toLowerCase().equals("yes")){
                if(!mobileElement.isSelected())
                    mobileElement.click();
            }
        }catch (Exception e){
            TestRegister.testResult = false;
            e.printStackTrace();
        }
    }

    public void input(MobileElement mobileElement, String data){
        try{
            this.click(mobileElement, data);
            mobileElement.clear();
            mobileElement.sendKeys(data);
        }catch (Exception e){
            TestRegister.testResult = false;
            e.printStackTrace();
        }
    }

    public void verify(MobileElement mobileElement, String data){
        String actualResult;
        try{
            actualResult = mobileElement.getAttribute("text");
            if(!actualResult.equals(data)){
                TestRegister.testResult = false;
            }
        }catch (Exception e){
            TestRegister.testResult = false;
        }
    }

    public static void waitForLoadingActivity(MobileElement mobileElement, String data)throws InterruptedException{
        Thread.sleep(3000);
        log.info(driver.currentActivity());
        int activityInspectCount, activityInspectInterval;
        activityInspectCount = Constants.controllerInPage.activityInspectCount;
        activityInspectInterval = Constants.controllerInPage.activityInspectInterval;
        int i =0;
        Thread.sleep(activityInspectInterval);
        while(i<activityInspectCount){
            try{
                if(data.contains(driver.currentActivity())){
                    log.info(data+"come out!");
                    break;
                }else {
                    log.info(data+"did not come out,Waiting........");
                    Thread.sleep(activityInspectInterval);
                    i++;
                }
            }catch (Exception e){
                i++;
                log.info("try" + activityInspectCount + "times," +data+ "did not come out");
                TestRegister.testResult = false;
            }
        }
    }

    public void back(MobileElement mobileElement, String data){
        driver.pressKeyCode(AndroidKeyCode.BACK);
    }
}

测试代码

package com.davieyang.testScripts;
import com.davieyang.base.BaseActivity;
import com.davieyang.util.Action;
import com.davieyang.util.FindElement;
import com.davieyang.util.Constants;
import io.appium.java_client.MobileElement;
import com.davieyang.util.DataProviderFromExcel;

import java.lang.reflect.Method;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.apache.log4j.Logger;


public class TestRegister extends BaseActivity {
    Logger log = Logger.getLogger(TestRegister.class.getName());
    public static Method[] method;
    public static String inspector;
    public static String data;
    public static String actionstep;
    public static Action action;
    public static MobileElement mobileElement;
    public static boolean testResult;
    public static String filePath;

    @Test
    public void testRegisterSuccess() throws Exception {
        action = new Action(getDriver());
        method = action.getClass().getMethods();
        String filePath = Constants.excelFile.filePath;
        DataProviderFromExcel.getExcel(filePath);
        String fileSheet = Constants.dispatcherSheet.suite_sheet;
        // 获取测试集合中测试用例的总数
        int testSuiteAllNum = DataProviderFromExcel.getAllRowNum(fileSheet);
        // 循环测试调度文件
        for (int testSuiteNum = 1; testSuiteNum <= testSuiteAllNum; testSuiteNum++) {
            // 获取测试用例名,直接关联待测试用例所在的sheet名
            String testCaseName = DataProviderFromExcel.getCellData(Constants.dispatcherSheet.suite_sheet,
                    testSuiteNum, Constants.dispatcherSheet.suite_testCaseName).trim();
            // 判断测试用例是否运行
            String isRun = DataProviderFromExcel.getCellData(Constants.dispatcherSheet.suite_sheet, testSuiteNum,
                    Constants.dispatcherSheet.suite_isRun).trim();
            // 获取测试用例详细的描述,用来输出日志
            String testCaseDetail = DataProviderFromExcel.getCellData(Constants.dispatcherSheet.suite_sheet, testSuiteNum,
                    Constants.dispatcherSheet.suite_testCaseDetail).trim();
            // 如果isRun的值为yes,则执行指定sheet页的测试步骤,sheet名与testCaseName相同
            if (isRun.equals("yes")) {
                // 测试用例执行结果默认为失败
                log.info("运行测试用例:测试用例名称为" + testCaseName + ";测试用例详细描述:" + testCaseDetail);
                testResult = true;
                int testCaseAllNum = DataProviderFromExcel.getAllRowNum(testCaseName);
                log.info("测试步骤:" + testCaseAllNum);
                for (int testCaseNum = 1; testCaseNum <= testCaseAllNum; testCaseNum++) {
                    // 获取识别方式
                    inspector = DataProviderFromExcel.getCellData(testCaseName, testCaseNum, Constants.testCaseSheet.Col_inspector).trim();
                    // 获取操作逐句
                    data = DataProviderFromExcel.getCellData(testCaseName, testCaseNum, Constants.testCaseSheet.Col_data).trim();
                    // 获取操作方式
                    actionstep = DataProviderFromExcel.getCellData(testCaseName, testCaseNum, Constants.testCaseSheet.Col_actionStep).trim();
                    // 识别元素
                    mobileElement = null;
                    if (!inspector.isEmpty()) {
                        mobileElement = FindElement.findElement(driver, inspector);
                    }
                    log.info("执行测试步骤:识别方式" + inspector + ";操作:" + actionstep + ";测试数据:" + data);
                    execute_Action(testCaseNum, testCaseName);
                    if (testResult == false) {
                        log.info("测试用例执行结果为false");
                        DataProviderFromExcel.setCellData(testSuiteNum, Constants.dispatcherSheet.suite_result, false, fileSheet, filePath);
                        Assert.fail("测试步骤有失败,整个测试用例执行失败");
                        break;
                    }
                    if (testResult) {
                        log.info("测试用例执行结果为true");
                        DataProviderFromExcel.setCellData(testSuiteNum, Constants.dispatcherSheet.suite_result, true, fileSheet, filePath);
                        Assert.assertTrue(true, "测试用例执行成功");
                    }
                }
            }
        }


    }

    public void execute_Action(int testCaseNum, String testCaseName) throws Exception {
        try {
            for (int i = 0; i <= method.length; i++) {
                if (method[i].getName().equals(actionstep)) {
                    method[i].invoke(action, mobileElement, data);
                    if (testResult) {
                        log.info("测试步骤执行结果为True");
                        DataProviderFromExcel.setCellData(testCaseNum, Constants.testCaseSheet.Col_result, true, testCaseName, Constants.excelFile.filePath);
                        break;
                    } else {
                        log.info("测试步骤执行结果为False");
                        DataProviderFromExcel.setCellData(testCaseNum, Constants.testCaseSheet.Col_result, false, testCaseName, Constants.excelFile.filePath);

                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/108333143