zoukankan      html  css  js  c++  java
  • 关于自动化测试框架,所需代码技能,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");

    控制台上的执行结果:

    至此,本文介绍完毕。

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

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

  • 相关阅读:
    LeetCode 109 Convert Sorted List to Binary Search Tree
    LeetCode 108 Convert Sorted Array to Binary Search Tree
    LeetCode 107. Binary Tree Level Order Traversal II
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 103 Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 104. Maximum Depth of Binary Tree
    接口和多态性
    C# 编码规范
  • 原文地址:https://www.cnblogs.com/iceb/p/7629480.html
Copyright © 2011-2022 走看看