关于自动化测试框架,所需代码技能,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");
    }

}

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);

……

待续……

时间: 2024-10-04 04:32:22

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

Java自动化测试框架-03 - TestNG之Test Group篇 - 我们一起组团打怪升级(详细教程)

简介 其实这篇文章的group宏哥在上一篇中就提到过,但是就是举例一笔带过的,因此今天专门有一篇文章来讲解Group的相关知识.希望大家茅塞顿开 ,有着更进一步认识和了解测试组. 一.Test Group(测试组) TestNG 允许你将复杂的测试方法归类为不同的组.不仅仅是可以声明某个方法属于某个组,而且还可以让组包含其他的组.这样TestNG可以调用或者请求包含一组特定的组 (或者正则表达式)而排除其他不需要组的集合.这样,如果你打算将测试分成两份的时候,就无需重新编译.这个特点,会给你在划

Java自动化测试框架-09 - TestNG之依赖注入篇 (详细教程)

1.-依赖注入 TestNG支持两种不同类型的依赖项注入:本机(由TestNG本身执行)和外部(由诸如Guice的依赖项注入框架执行). 1.1-本机依赖项注入 TestNG允许您在方法中声明其他参数.发生这种情况时,TestNG将自动用正确的值填充这些参数.依赖注入可以在以下地方使用: 任何@Before方法或@Test方法都可以声明ITestContext类型的参数.任何@AfterMethod方法都可以声明ITestResult类型的参数,该参数将反映刚刚运行的测试方法的结果.任何@Bef

Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)

简介 前边一直在分享testng的相关文章,看了点赞量和阅读数不是很高,宏哥猜测估计是大家确实是用不到或者不喜欢吧!不过宏哥经过一段时间的准备,appium的自动化测试框架完善的差不多了,那么接下来宏哥继续给小伙伴和童鞋们分享有关Appium自动化测试框架综合实践.想必小伙伴们有点等不及了吧! driver配置封装 kyb_caps.yaml 配置表 主要是一些配置信息的封装. 参考代码 platformName: Android #模拟器 platformVersion: 5.1.1 devi

【SSH三大框架】Struts2基础第三篇:配置Action以及调用Action的三种方式

一.struts.xml中的包和命名空间 1.Struts2不支持为单独的Action设置命名空间,而是通过为包指定namespace属性来为包下面的所有Action指定共同的命名空间. 如果在配置<package>的时候没有指定namespace属性,则该包下的所有Action处于默认的包空间下 2.例如: <package name="lee" extends="struts-default"> <action name="

Selenium+java - 手把手一起搭建一个最简单自动化测试框架

写在前面 我们刚开始做自动化测试,可能写的代码都是基于原生写的代码,看起来特别不美观,而且感觉特别生硬. 来看下面一段代码,如下图所示: 从上面图片代码来看,具体特征如下: driver对象在测试类中显示 定位元素的value值在测试类中显示 定位元素的方式(By对象)在测试类中显示 代码一报错,还要去测试类里面找是哪段代码报错,要是代码行数几百行时呢,就不好定位问题了 这样的测试脚本组装批量执行,批量报错后,怒号排查,定位问题,很吃力 看看自己有几条命中呢,其他现象就不一一列举了. 1.为什么

java+Selenium+TestNg搭建自动化测试架构(1)实现代码和数据的分离

1.主要介绍介绍Java+Selenium+POM的自动化测试框架的搭建,第一个首先实现代码和账号URL等信息的分离.第二点支持跨浏览器,通过读取配置文件的方式实现. 1)将账号URL等信息添加在properties文件中然后读取 2)编写浏览器类通过去取配置文件实现浏览器的切换 3)测试浏览器类 项目结构: 1.新建一个文件夹将properties文件放在文件夹中内容如下: # browser switcher #browserName = FirefoxbrowserName = Chrom

Java+Maven+selenium+testing+reportNG自动化测试框架

最近公司新出了一个产品,需要搭建自动化测试框架,这是一个学以至用的好机会,跟上级申请后,决定搭建一个java自动化测试框架. Java自动化测试对我来讲可以说不难不易,因为java是我大学在校四年学的主要开发语言,但是毕业这么多年没写了难免生疏. weiUI自动化测试需要掌握以下几点:一是获取元素,java获取元素对象与python差不多,用的是findElement方法,不过我在搭建框架过程中为了实现PO模式,从万能的百度中获知还有个一更好的类FindBy,FindBy+PageFactory

代码生成java连接数据库的所需代码(超详细)

开始学习: round 1:(一开始学习当然还是要一步一步学习的啦,哪有什么一步登天!!!) a.准备工作:1.eclipse,mysql(这两个软件肯定要的啦,不然学什么把它们连接起来) 2.加载驱动jar包:mysql-connector-java-5.1.40.jar(我用的是这个版本,你们随意!) b.创建工程,把jar包导进工程中的lib下面,然后右击build path把jar包添加进工程中 c.创建数据库books,添加相关字段 d.创建与数据库的连接及查看数据库信息 1 impo

Python Api接口自动化测试框架 代码写用例

公司新来两个妹子一直吐槽这个接口测试用例用excel维护起来十分费脑费事,而且比较low(内心十分赞同但是不能推翻自己),妹子说excel本来就很麻烦的工具,于是偷偷的进行了二次改版. 变更内容如下: 1.代码结构 image.png 2.新增测试报告网页版和版本管理 3.新增用例代码化 一.封装一个获取用例的模块 image.png 用例的写法可以按照yml文件的写法,后缀的文件都可为.conf..config..ini.[]中的是测试用例场景,下面的参数内容对应接口用例参数. 简单介绍下py