java自动化之自动化框架项目(第二天-读取数据文件并封装对象)

时间:2024-03-03 12:27:38

接第一天

1.实现目标

把excel中数据读取出来,并封装到对象中,这样注入测试数据到测试方法的时候,一次注入一个对象,而不用写很多参数,另外,获取测试数据(比如url等),直接通过对象的get方法就可以很方便的获取到。

2.添加pom依赖

操作excel的依赖

pom.xml中添加如下配置

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>      

3.测试数据文件放caseData目录

caseData-解决韧.xlsx

caseData-解决韧.xlsx文件可在资源中自行下载

4.修改testng.xml

指定参数:数据文件路径、用例sheet名、常用变量sheet名

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="apiAutoTest" verbose="1">
    <test name="register-login-add-findByName" enabled="true">  <!--test必须有name属性-->
        <parameter name="excelPath" value="caseData/外卖系统接口测试用例-V1.5.xls"/>
        <parameter name="dataSheetName" value="登录模块"/>
        <classes>
            <class name="com.syq.autotest.testcase.BaseCase"/>
        </classes>
    </test>
</suite>

5.创建实体类

用例

package com.syq.autotest.entity;

/**
 * @description
 * @author: Admin
 * @create: 2024/1/29 15:55
 */
public class CaseData {
    //用例id
    private String caseId;
    //接口名称
    private String apiName;
    //描述
    private String describe;
    //url-只写路径,不需要写ip、端口
    private String url;
    //请求类型:目前只支持post、get
    private String requestType;
    //Headers:json格式字符串,如果没有请求头,填写为{}
    private String headers;
    //Cookies:预留,暂未使用
    private String cookies;
    //Parameters:json格式字符串,如果是非关联变量(也就是上面的常用变量),填写为#{xxx},如果是关联参数,填写为${xxx}
    private String parameters;
    //UploadFile:预留,暂未使用
    private String uploadFile;
    //InitSql:初始化sql,要求是json数组,例如:[{"sqlNo":"1","sql":"delete from users where username = '#{username}';"}],用到的常用变量,填写为#{xxx}
    private String initSql;
    //GlobalVariables:需要关联的参数值,样例:token=$.token;,左侧是字段名,右侧是其jsonpath路径,并以英文分号结尾,多个断言字段用英文分号间隔
    private String globalVariables;
    //AssertFields:要断言字段的jsonpath路径以及值,并以英文分号结尾,多个断言字段用英文分号间隔,如:$.code=9550;$.msg=success;
    private String assertFields;

    public String getCaseId() {
        return caseId;
    }

    public void setCaseId(String caseId) {
        this.caseId = caseId;
    }

    public String getApiName() {
        return apiName;
    }

    public void setApiName(String apiName) {
        this.apiName = apiName;
    }

    public String getDescribe() {
        return describe;
    }

    public void setDescribe(String describe) {
        this.describe = describe;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public String getHeaders() {
        return headers;
    }

    public void setHeaders(String headers) {
        this.headers = headers;
    }

    public String getCookies() {
        return cookies;
    }

    public void setCookies(String cookies) {
        this.cookies = cookies;
    }

    public String getParameters() {
        return parameters;
    }

    public void setParameters(String parameters) {
        this.parameters = parameters;
    }

    public String getUploadFile() {
        return uploadFile;
    }

    public void setUploadFile(String uploadFile) {
        this.uploadFile = uploadFile;
    }

    public String getInitSql() {
        return initSql;
    }

    public void setInitSql(String initSql) {
        this.initSql = initSql;
    }

    public String getGlobalVariables() {
        return globalVariables;
    }

    public void setGlobalVariables(String globalVariables) {
        this.globalVariables = globalVariables;
    }

    public String getAssertFields() {
        return assertFields;
    }

    public void setAssertFields(String assertFields) {
        this.assertFields = assertFields;
    }

    @Override
    public String toString() {
        return "CaseData{" +
                "caseId='" + caseId + '\'' +
                ", apiName='" + apiName + '\'' +
                ", describe='" + describe + '\'' +
                ", url='" + url + '\'' +
                ", requestType='" + requestType + '\'' +
                ", headers='" + headers + '\'' +
                ", cookies='" + cookies + '\'' +
                ", parameters='" + parameters + '\'' +
                ", uploadFile='" + uploadFile + '\'' +
                ", initSql='" + initSql + '\'' +
                ", globalVariables='" + globalVariables + '\'' +
                ", assertFields='" + assertFields + '\'' +
                '}';
    }
}

常用变量

package com.syq.autotest.entity;

/**
 * @description
 * @author: Admin
 * @create: 2024/1/29 16:10
 */
public class Variable {
    /**
     * name:变量名,#{xxx}整体表示变量名
     * value:变量值
     * description:变量的描述
     */
    private String name;
    private String value;
    private String description;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Variable{" +
                "name='" + name + '\'' +
                ", value='" + value + '\'' +
                ", description='" + description + '\'' +
                '}';
    }
}

6.创建工具类

ExcelUtil.java,读取excel文件中的数据

package com.syq.autotest.utils;

import org.apache.poi.ss.usermodel.*;
import org.testng.log4testng.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @description
 * @author: Admin
 * @create: 2024/1/29 16:33
 */
public class ExcelUtil {
    public static Logger logger = Logger.getLogger(ExcelUtil.class);

    // 解析指定excel表单的数据,封装到对象中【对象类型使用泛型】
    public static <T> List<T> loadExcel(String excelPath, String sheetName, Class<T> clazz){
        logger.info("===================开始读取sheet: " + sheetName);
        // 创建一个list
        List<T> list = new ArrayList<T>();
        InputStream in = null;
        // 创建WorkBook对象
        try {
            File file = new File(excelPath);
            in = new FileInputStream(file);
            // 获取workbook对象
            Workbook workbook = WorkbookFactory.create(in);
            // 获取sheet对象
            Sheet sheet = workbook.getSheet(sheetName);
            // 获取第一行,Row是行对象类型,通过行对象可以操作列
            Row firstRow = sheet.getRow(0);
            // 获取最后一列的列号
            int lastCellNum = firstRow.getLastCellNum();
            // System.out.println(lastCellNum);

            // 定义存放表头的数组
            String[] titles = new String[lastCellNum];
            // 将表头放入数组
            for (int i = 0; i < lastCellNum; i++) {
                // 通过行对象和列索引,获取单元格对象
                Cell cell = firstRow.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                // 设置列的类型为字符串
                // cell.setCellType(CellType.STRING);
                // 获取单元格的值
                String title = cell.getStringCellValue();
                // title = title.substring(0,title.indexOf(":"));
                // 值保存到数组
                titles[i] = title;
            }
            // 打印解析出来的标题
            // logger.info("解析出来的首行标题:" + Arrays.toString(titles));

            // 获取sheet最后一行的行号
            int lastRowNum = sheet.getLastRowNum();
            // System.out.println(lastRowNum);
            // 循环处理每一行数据,从2行开始是数据行
            for (int i = 1; i <= lastRowNum  ; i++) {
                // 每行数据一个对象
                T obj = clazz.newInstance();
                // 获取一行数据
                Row rowData = sheet.getRow(i);
                if (rowData==null || rowDataIsEmpty(rowData)){
                    continue;
                }
                // 获取此行的列数据,封装到caseObject对象中
                for (int j = 0; j < lastCellNum ; j++) {
                    Cell cell = rowData.getCell(j, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                    cell.setCellType(CellType.STRING);
                    String cellValue = cell.getStringCellValue();
                    // 打印获取到的值
                    // System.out.print("【"+ titles[j] + "="+ cellValue+"】");
                    // 获取要反射的方法名
                    String methodName = "set" + titles[j];
                    // 获取要反射的方法对象
                    Method method = clazz.getMethod(methodName, String.class);
                    // 反射调用
                    method.invoke(obj, cellValue);
                }
                // logger.info("封装的第【"+i+"】个对象(也就是第"+i+"行数据):" + obj);
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        logger.info("===================读取sheet完成: " + sheetName);
        return list;
    }


    // 判断行的单元格数据是否都是空
    public static boolean rowDataIsEmpty(Row rowData) {
        int lastCellNum = rowData.getLastCellNum();
        for (int i = 0; i < lastCellNum; i++) {
            Cell cell = rowData.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
            cell.setCellType(CellType.STRING);
            String cellValue = cell.getStringCellValue();
            if (cellValue!=null && cellValue.trim().length()>0){
                return false;
            }
        }
        return true;
    }
}

7.修改测试类

package com.syq.autotest.testcase;

import com.syq.autotest.entity.CaseData;
import com.syq.autotest.entity.Variable;
import com.syq.autotest.utils.ExcelUtil;
import org.testng.annotations.*;
//import org.testng.log4testng.Logger;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;

/**
 * @description
 * @author: Admin
 * @create: 2024/1/26 16:21
 */
public class BaseCase {
    public static Logger logger = Logger.getLogger(BaseCase.class);

    // 保存所有用例对象
    public static List<CaseData> cases = new ArrayList<CaseData>();
    // 存放变量对象的列表
    public static List<Variable> variables = new ArrayList<Variable>();


    @Parameters({ "excelPath", "dataSheetName", "variableSheetName"})
    @BeforeTest
    public void readDataFromExcel(@Optional("caseData/caseData-解决韧.xlsx") String excelPath, @Optional("case") String dataSheetName, @Optional("variables") String variableSheetName){
        logger.info("excelPath: " + excelPath);
        logger.info("dataSheetName: " + dataSheetName);
        logger.info("variableSheetName: " + variableSheetName);
        cases = ExcelUtil.loadExcel(excelPath, dataSheetName, CaseData.class);
        variables = ExcelUtil.loadExcel(excelPath, variableSheetName, Variable.class);
        logger.info("读取文件获取到的cases对象:" + cases);
        logger.info("读取文件获取到的variables对象:" + variables);
    }
}

8.结果演示

运行xml文件

通过上面结果可以看到,数据已经读取成功并保存到对象中。

如有需要全部代码文件,可在资源中自行获取,有其他问题,可在评论区评论!!!