• 关于自动化测试框架,所需代码技能,Java篇——参数配置与读取.


    前言:

      说在前边。像我这种假期不出去浪,在这里乖乖写文章研究代码的人,绝壁不是因为爱学习,而是自己不知道去哪玩好,而且也不想玩游戏,看电视剧什么的,结果就无聊到看代码了……

      至于如何解读代码,请把它当做一门语言,况且它就是语言 ,计算机的,那就当做是外国人的语言,可以翻译成汉语的!

      例:system.out.print(" ") 翻译:系统.输出.打印(内容)。如是说!

    本文介绍:

    • PropertiesCsvExcelJDBC

    初级架构所需代码之 参数配置与读取——properties

      一般代码中需要读取配置有几种方式,在此一一举例说明吧~

      首先,比较常见的是读取properties。一般,我们会将该文件存放在resource当中。

    需要了解和使用的几个主要方法:

    1.getProperty ( String key),通过参数 key ,得到 key 所对应的 value。

    2.load ( InputStream inStream),读取配置,以供 getProperty ( String key) 来搜索。

    3.setProperty ( String key, String value) ,set设置,也就是说设置key-value。

    4.store ( OutputStream out, String comments),与 load 方法相反,该方法将 key-value 写入到指定的文件中去。

    5.clear (),清除所有装载的key-value。该方法在基类中提供。

    1和2搭配使用,3和4搭配使用。

    实例解说

    相比概念性的东西,伸手党以及新手们更喜欢实例的东西来说明。

    假如test.properties文件如下:

    name=root
    pass=admin
    key=value

    那么读取和使用的方法如下(网上最多的文章是6种properties配置读取方法,我这里推荐使用最常用的是这种):

    Properties properties = new Properties();  //调用该方法,不要问为什么
    InputStream in =null;  //初始化输入流
    in = Obejct.class.getResourceAsStream("/config.properties");  //获取该路径下的properties数据
    try {
           properties.load(in);  //读取数据
        } catch (IOException e) {
           e.printStackTrace();
        }
    properties.getProperty("pass");  //根据key获取values

    最后获取的值就是pass对应的admin.(注意你的路径是否正确,以免报错nullPoint

    针对以上的例子,我们看到这样的一句

    Obejct.class.getResourceAsStream(path)  //path表示你的properties路径

    为了安全起见,更推荐将Obejct改写成你的当前类名,比如 readProperties.class.getResourceAsStream("路径").

    参数读取与使用——csv

    TestNg中csv数据读取与使用,可以利用此结构遍历csv中的数据,让用例循环执行,直到数据全部读取完毕。

    我们新建add.csv到你的任意目录中,比如我的放在这里:

    1.直接上代码,首先是csv的数据:

    2.创建两个类,一个是基类,用来实现n1+n2=r1这样的功能:

    public class Calculator {
        public Float add(Float num1,Float num2){
            return num1+num2;
        }
    }

    一个是工具类,用来读取csv中的数据:

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.TreeMap;
    import java.util.regex.Matcher;
    
    public class CsvUtils implements Iterator<Object[]> {
        BufferedReader in;
        ArrayList<String> csvList=new ArrayList<String>();
        int rowNum=0;     //行数
        int columnNum=0;  //列数
        int curRowNo=0;   //当前行数
        String columnName[];  //列名
        /**
         * 在TestNG中由@DataProvider(dataProvider = "name")修饰的方法取csv数据时,
         * 调用此类构造方法(此方法会得到列名),
         * 返回给由@Test(dataProvider = "name")修饰的方法,如此
         * 反复到数据读完为止
         * @param fileName 文件名
         * @throws IOException
         */
        public CsvUtils(String fileName) throws IOException{
            File directory=new File(".");
            String path=".src.main.java.page.testdata.";    //文件路径
            String absolutePath=directory.getCanonicalPath()+path.replaceAll("\.", Matcher.quoteReplacement("\"))+fileName;
            System.out.println(absolutePath);   //打印路径
            File csv=new File(absolutePath);
            in=new BufferedReader(new FileReader(csv)); //读取csv数据
            while (in.ready()) {
                csvList.add(in.readLine());
                this.rowNum++;
            }
            String[] str=csvList.get(0).split(",");
            this.columnNum=str.length;
            columnName=new String[columnNum];
            //获取列名
            for (int i = 0; i < columnNum; i++) {
                columnName[i]=str[i];
            }
            this.curRowNo++;
        }
        @Override
        public boolean hasNext() {
            // TODO Auto-generated method stub
            if(rowNum==0||curRowNo>=rowNum){
                try {
                    in.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return false;
            }else{
                return true;
            }
        }
        /**
         * 获取一组参数,即一行数据
         */
        @Override
        public Object[] next() {
            // TODO Auto-generated method stub
            Map<String,String> s=new TreeMap<String,String>();
            String csvCell[]=csvList.get(curRowNo).split(",");
            for(int i=0;i<this.columnNum;i++){
                s.put(columnName[i], csvCell[i]);
            }
            Object[] d=new Object[1];
            d[0]=s;
            this.curRowNo++;
            return d;
        }
    
        @Override
        public void remove() {
            // TODO Auto-generated method stub
            throw new UnsupportedOperationException("remove unsupported");
        }
    
    }
    CSVUtils

    3.实现类

    import java.io.IOException;
    import java.util.Iterator;
    import java.util.Map;
    
    import core.utils.CsvUtils;
    import org.testng.Assert;
    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Test;
    
    
    public class CsvTest{
        Calculator cal=new Calculator();
    
        @DataProvider(name="num")
        public Iterator<Object[]> Numbers() throws IOException{
            return (Iterator<Object[]>)new CsvUtils("add.csv");
        }
        @Test(dataProvider="num")
        public void testAdd(Map<String, String> data){
            float num1=Float.parseFloat(data.get("n1"));
            float num2=Float.parseFloat(data.get("n2"));
            float expectedResult=Float.parseFloat(data.get("r1"));
            Float actual=cal.add(num1, num2);
            Assert.assertEquals(actual, expectedResult);
        }
    }

    4.执行结果:

    不要光看,自己敲一遍就知道什么意思了!

    Excel数据的读取

    对于已经写好了脚本的同学,多数采用的是这种数驱的形式,这种形式很方便维护自己的用例,完全不用打开编译器,改改数据就好。

    但是,它也同样存在弊端,比如数据量相对大起来的时候,比如需要网络调用的时候,我们都没有很好的办法去维护它,不过我们同样要掌握这种数据读取和使用的方法。

    针对于Excel还有个要考虑的问题,那就是版本的问题,因为excel分为97-03,07+版,也就是文件后缀是.xls.xlsx的两种版本(官网为什么不把14年前的版本干掉……要统一啊~),

    所以,我们还要针对这两种情况来整合封装一个类,来实现根据后缀名判断调用方法。

    可以实现该功能的包有两个:poijxl至于优势和劣势自己网上搜吧。

    1.这里先介绍下POI的一些用法,首先它更适用于97-2008版本的Excel(Apache-POI官网);

    可能会用到的字段说明:

    • HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
    • XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
    • HWPF - 提供读写Microsoft Word DOC格式档案的功能。
    • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
    • HDGF - 提供读Microsoft Visio格式档案的功能。
    • HPBF - 提供读Microsoft Publisher格式档案的功能。
    • HSMF - 提供读Microsoft Outlook格式档案的功能。

    关于Maven引用:

    <!-- poi-ooxml同时支持XLS和XLSX两种格式 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.17</version>
    </dependency>

     思路:

    创建读取Excel-xlsx格式的类;

    /**
         * 读取2007-2013格式
         * @param filePath 文件路径
         * @return excel以数组形式返回
         * @throws java.io.IOException
         */
        @SuppressWarnings("rawtypes")
        public static List<Map> readXLSX(String filePath) throws IOException {
            List<Map> valueList = new ArrayList<Map>();
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(filePath);
                XSSFWorkbook xwb = new XSSFWorkbook(fis);   // 构造 XSSFWorkbook 对象,strPath 传入文件路径
                XSSFSheet sheet = xwb.getSheetAt(0);            // 读取第一章表格内容
                // 定义 row、cell
                XSSFRow row;
                // 循环输出表格中的第一行内容   表头
                Map<Integer, String> keys = new HashMap<Integer, String>();
                row = sheet.getRow(0);
                if (row != null) {
                    //System.out.println("j = row.getFirstCellNum()::"+row.getFirstCellNum());
                    //System.out.println("row.getPhysicalNumberOfCells()::"+row.getPhysicalNumberOfCells());
                    for (int j = row.getFirstCellNum(); j <= row.getPhysicalNumberOfCells(); j++) {
                        // 通过 row.getCell(j).toString() 获取单元格内容,
                        if (row.getCell(j) != null) {
                            if (!row.getCell(j).toString().isEmpty()) {
                                keys.put(j, row.getCell(j).toString());
                            }
                        } else {
                            keys.put(j, "K-R1C" + j + "E");
                        }
                    }
                }
                // 循环输出表格中的从第二行开始内容
                for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getPhysicalNumberOfRows(); i++) {
                    row = sheet.getRow(i);
                    if (row != null) {
                        boolean isValidRow = false;
                        Map<String, Object> val = new HashMap<String, Object>();
                        for (int j = row.getFirstCellNum(); j <= row.getPhysicalNumberOfCells(); j++) {
                            XSSFCell cell = row.getCell(j);
                            if (cell != null) {
                                String cellValue = null;
                                if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC) {
                                    if (DateUtil.isCellDateFormatted(cell)) {
                                        cellValue = new DataFormatter().formatRawCellContents(cell.getNumericCellValue(), 0, "yyyy-MM-dd HH:mm:ss");
                                    } else {
                                        cellValue = String.valueOf(cell.getNumericCellValue());
                                    }
                                } else {
                                    cellValue = cell.toString();
                                }
                                if (cellValue != null && cellValue.trim().length() <= 0) {
                                    cellValue = null;
                                }
                                val.put(keys.get(j), cellValue);
                                if (!isValidRow && cellValue != null && cellValue.trim().length() > 0) {
                                    isValidRow = true;
                                }
                            }
                        }
    
                        // 第I行所有的列数据读取完毕,放入valuelist
                        if (isValidRow) {
                            valueList.add(val);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                fis.close();
            }
            return valueList;
        }
    readXLSX

    创建读取Excel-xls格式的类;

     /**
         * 读取97-2003格式
         * @param filePath 文件路径
         * @throws java.io.IOException
         */
        @SuppressWarnings("rawtypes")
        public static List<Map> readXLS(String filePath) throws IOException{
            //返回结果集
            List<Map> valueList=new ArrayList<Map>();
            FileInputStream fis=null;
            try {
                fis=new FileInputStream(filePath);
                HSSFWorkbook wookbook = new HSSFWorkbook(fis);  // 创建对Excel工作簿文件的引用
                HSSFSheet sheet = wookbook.getSheetAt(0);   // 在Excel文档中,第一张工作表的缺省索引是0
                int rows = sheet.getPhysicalNumberOfRows(); // 获取到Excel文件中的所有行数­
                Map<Integer,String> keys=new HashMap<Integer, String>();
                int cells=0;
                // 遍历行­(第1行  表头) 作为Map里的key
                HSSFRow firstRow = sheet.getRow(0);
                if (firstRow != null) {
                    // 获取到Excel文件中的所有的列
                    cells = firstRow.getPhysicalNumberOfCells();
                    // 遍历列
                    for (int j = 0; j < cells; j++) {
                        // 获取到列的值­
                        try {
                            HSSFCell cell = firstRow.getCell(j);
                            String cellValue = getCellValue(cell);
                            keys.put(j,cellValue);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                // 遍历行­(从第二行开始)
                for (int i = 1; i < rows; i++) {
                    // 读取左上端单元格(从第二行开始)
                    HSSFRow row = sheet.getRow(i);
                    // 行不为空
                    if (row != null) {
                        //准备当前行 所储存值的map
                        Map<String, Object> val=new HashMap<String, Object>();
    
                        boolean isValidRow = false;
    
                        // 遍历列
                        for (int j = 0; j < cells; j++) {
                            // 获取到列的值­
                            try {
                                HSSFCell cell = row.getCell(j);
                                String cellValue = getCellValue(cell);
                                val.put(keys.get(j),cellValue);
                                if(!isValidRow && cellValue!=null && cellValue.trim().length()>0){
                                    isValidRow = true;
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        //第I行所有的列数据读取完毕,放入valuelist
                        if(isValidRow){
                            valueList.add(val);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                fis.close();
            }
            return valueList;
        }
    
        /**
         * 返回表内正确的内字符类型
         * @param cell 表格
         * @return
         */
        private static String getCellValue(HSSFCell cell) {
            DecimalFormat df = new DecimalFormat("#");
            String cellValue=null;
            if (cell == null)
                return null;
            switch (cell.getCellType()) {
                case HSSFCell.CELL_TYPE_NUMERIC:
                    if(HSSFDateUtil.isCellDateFormatted(cell)){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        cellValue=sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                        break;
                    }
                    cellValue=df.format(cell.getNumericCellValue());
                    break;
                case HSSFCell.CELL_TYPE_STRING:
                    cellValue=String.valueOf(cell.getStringCellValue());
                    break;
                case HSSFCell.CELL_TYPE_FORMULA:
                    cellValue=String.valueOf(cell.getCellFormula());
                    break;
                case HSSFCell.CELL_TYPE_BLANK:
                    cellValue=null;
                    break;
                case HSSFCell.CELL_TYPE_BOOLEAN:
                    cellValue=String.valueOf(cell.getBooleanCellValue());
                    break;
                case HSSFCell.CELL_TYPE_ERROR:
                    cellValue=String.valueOf(cell.getErrorCellValue());
                    break;
            }
            if(cellValue!=null&&cellValue.trim().length()<=0){
                cellValue=null;
            }
            return cellValue;
        }
    readXLS

    根据文件名选择执行对应的类;

    /**
         * 根据文件名自动识别读取方式
         * 同时支持xls及xlsx格式的Excel数据读取
         *
         * @param filepath 文件名:包含路径及扩展名
         * @return 返回列表内容格式:
         * 每一行数据都是以对应列的表头为key 内容为value 比如 excel表格为:
         * ===============
         * A | B | C | D
         * ===|===|===|===
         * 1 | 2 | 3 | 4
         * ---|---|---|---
         * a | b | c | d
         * ---------------
         * 返回  [{A=1, B=2, C=3, D=4}, {A=a, B=b, C=c, D=d}]
         * @throws java.io.IOException
         */
        public static List<Map> readExcel(String filepath) {
            List<Map> valueList = new ArrayList<Map>();
    
            try {
                if (new FileUtils().getuffix(filepath).equalsIgnoreCase("xlsx")) {
                    valueList = ExcelUtils.readXLSX(filepath);
                }
                if (new FileUtils().getuffix(filepath).equalsIgnoreCase("xls")) {
                    valueList = ExcelUtils.readXLS(filepath);
                } else {
                    throw new ErrorOnSettingException("此文件不是Excel文件");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return valueList;
        }
    readExcel

    文件名工具类;

    public class FileUtils {
        /**
         * 获取文件名
         *
         * @param fileName 文件名包含扩展名
         * @return 返回获取的文件名
         */
        public String getFileName(String fileName) {
            fileName = fileName.trim();
            String fName = fileName.substring(fileName.lastIndexOf("/") + 1);
            return fName;
        }
    }
    FileUtils

    实现类:

    ExcelUtils.readExcel(filepath);

     JDBC数据的读取

    本文最后要介绍JDBC的数据读取,如何使用数据库的数据到你的脚本中使用,也是数据参数驱动的一种常用方式;

    针对数据量相对大的场景,首推数据库来保存你的参数,也更方便维护;

    相对于其他方式,jdbc在使用结束后,一定要关闭输入流,就像webdriver使用结束后要有个webdriver.close()是一样的,下边的代码中你也可以看到。

     假如数据库中的数据如下:

    数据库配置与链接:

            // 数据库类型
            private static String DBTYPE = "mysql";
            // 数据库地址 格式:jdbc:mysql://ip:port/tablename?参数(可有可无,根据需要添加参数)
            private static String DB_URL = "jdbc:mysql://localhost:3306/antmember_test?characterEncoding=utf8&useSSL=true&serverTimezone=UTC";
            // 数据库登录账号
            private static String USERNAME = "";
            // 数据库登录密码
            private static String PASSWORD = "";
            // 数据库表名
            private static String TABLENAME = "";
            // 链接数据库
            private static Connection conn = null;
            // 向数据库发送sql语句
            private static Statement statement = null;
            // 返回sql执行结果
            private static ResultSet resultSet = null;
            
            /**
             * 根据config配置信息,链接对应的数据库
             */
            public static void dbConnect () {
            
                System.out.println("读取数据库配置并开始链接");
                try {
                    if (DBTYPE.equals("mysql")) {
                        Class.forName("com.mysql.cj.jdbc.Driver");
                    }
                    if (DBTYPE.equals("oracle")) {
                        Class.forName("oracle.jdbc.driver.OracleDriver");
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
    
            }
    配置与链接

    数据库的查询:

            public static void dbSelect (String sql, String detail){
                dbConnect();
                try {
                    //登录数据库
                    conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
                    //创建并执行sql语句
                    statement = conn.prepareStatement(sql);
                    //返回sql执行结果
                    resultSet = statement.executeQuery(sql);
    
                    JsonObject object = new JsonObject();
                    JsonArray array = new JsonArray();
    
                    while (resultSet.next()) {
                        JsonObject ob = new JsonObject();
                        ob.addProperty(detail, resultSet.getString(detail));
                        array.add(ob);
                    }
                    object.add("查询结果:", array);
                    System.out.println(object.toString());
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        resultSet.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    try {
                        statement.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
            }
    查询

    为了方便查看返回结果,我还用了json解析格式输出到控制台中,同样,你也可以输出到你的文档中,或者日志当中(json解析需要引入gson这个jar包,maven的方法我就不说了),另外,关于其他数据库的链接方式如下:

    # 连接MySql数据库:Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
    # 连接Oracle数据库:Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password");
    # 连接SqlServer数据库:Connection conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://host:port; DatabaseName=database", "user", "password");
    # 其他参数如:useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC

    使用:

        //我的表名:sm_user_info
        String sql = "SELECT * FROM sm_user_info WHERE id_type = 'git'";
           dbSelect(sql, "user_id");

    控制台上的执行结果:

    至此,本文介绍完毕。

    当然还有很多可以讲的东西,大家不妨如此这般的各种尝试一下吧。

    有问题可以留言下方,我会及时解答,并补充说明

  • 相关阅读:
    操作系统(生产者、消费者问题)
    Hibernate——离线查询
    计算机网络(物理层习题)
    Mysql(笛卡尔积、等值连接、自然连接、外连接)
    vim文本编辑器——文件导入、命令查找、导入命令执行结果、自定义快捷键、ab命令、快捷键的保存
    vim文本编辑器——替换、保存退出
    CT107D电路解析
    vim文本编辑器——删除、复制、剪切、更改某一个字符、替换、撤销、关键字搜索
    文本编辑器vim——三种模式、显示行号、插入命令、行快速定位、行内定位
    关机、重启、退出登录命令
  • 原文地址:https://www.cnblogs.com/iceb/p/7629480.html
Copyright © 2020-2023  润新知