本文旨在帮助读者介绍,如何使用excle实现数据驱动
  本文是上文https://www.cnblogs.com/xuezhezlr/p/9096063.html的继续,如果没看上文建议自己看一下,对理解本文有很大帮助
  上文中的程序是较为原始的数据驱动,虽然实现了数据驱动,但是本质上还是把数据写在代码里来读取,这种方式只是为了实现数据驱动而去做的数据驱动,意义并不大而且提高代码要求的技术水平,提高代码复杂度,反而不如原有代码逻辑性强,本文承接上文来介绍
public static Collection zlrshiyan(){
return Arrays.asList(new Object[][]{{2,6},{3,5}});
}
  这部分是上文的代码中数据源头的片段,我们不禁想到,如果能从excle或者数据库等数据存储中取出数据,再加工为原有的字符串2维数据,即可使用这种方法,使得我们的数据源是excle,而代码是在另一个地方,运行时候读取即可
  下文是excle的读取方法
public static String[][] getxlsData(String file, int ignoreRows,String a)
throws FileNotFoundException, IOException{
File file1 = new File(file);
return getxlsData(file1,ignoreRows,a);
}
public static String[][] getxlsData(File file, int ignoreRows,String a)
throws FileNotFoundException, IOException {
List<String[]> result = new ArrayList<String[]>();
int rowSize = 0;
BufferedInputStream in = new BufferedInputStream(new FileInputStream(
file));
// 打开HSSFWorkbook
a = a.replaceAll("/","_");//替换a为xls可以接受的类型
a=a.substring(1,a.length()).trim();//去掉第一个_
POIFSFileSystem fs = new POIFSFileSystem(in);
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFCell cell = null;
int sheetIndex;
for (sheetIndex = 0; sheetIndex < wb.getNumberOfSheets(); sheetIndex++) {
if(wb.getSheetName(sheetIndex).equals(a))
{
break;
}
}
HSSFSheet st = wb.getSheetAt(sheetIndex);
// 第一行为标题,不取
for (int rowIndex = ignoreRows; rowIndex <= st.getLastRowNum(); rowIndex++) {
HSSFRow row = st.getRow(rowIndex);
if (row == null) {
continue;
}
int tempRowSize = row.getLastCellNum();
if (tempRowSize > rowSize) {
rowSize = tempRowSize;
}
String[] values = new String[rowSize];
Arrays.fill(values, "");
boolean hasValue = false;
for (short columnIndex = 0; columnIndex <= row.getLastCellNum()-1; columnIndex++) {
String value = "";
cell = row.getCell(columnIndex);
if (cell != null) {
// 注意:一定要设成这个,否则可能会出现乱码
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
value = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
if (date != null) {
value = new SimpleDateFormat("yyyy-MM-dd")
.format(date);
} else {
value = "";
}
} else {
value = new DecimalFormat("0").format(cell
.getNumericCellValue());
}
break;
case HSSFCell.CELL_TYPE_FORMULA:
// 导入时如果为公式生成的数据则无值
if (!cell.getStringCellValue().equals("")) {
value = cell.getStringCellValue();
} else {
value = cell.getNumericCellValue() + "";
}
break;
case HSSFCell.CELL_TYPE_BLANK:
break;
case HSSFCell.CELL_TYPE_ERROR:
value = "";
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
value = (cell.getBooleanCellValue() == true ? "Y"
: "N");
break;
default:
value = "";
}
}
if (columnIndex == 0 && value.trim().equals("")) {
break;
}
values[columnIndex] = rightTrim(value);
hasValue = true;
}

if (hasValue) {
result.add(values);
}
}
in.close();
String[][] returnArray = new String[result.size()][rowSize];
for (int i = 0; i < returnArray.length; i++) {
returnArray[i] = (String[]) result.get(i);
}
for(int i=1;i<returnArray.length;i++) {
returnArray[i][2] = returnArray[0][2] + "=" + returnArray[i][2];
for (int j = 3; j < returnArray[0].length; j++) {
returnArray[i][2] = returnArray[i][2] + "&" + returnArray[0][j] + "=" + URLEncoder.encode(returnArray[i][j],"utf-8");
}
}
String[][] returnArray2 = new String[result.size()-1][3];
for(int i=0;i<returnArray.length-1;i++)
for (int j = 0; j <= 2; j++) {
returnArray2[i][j]=returnArray[i+1][j];
}

return returnArray2;
}

/**
* 去掉字符串右边的空格
* @param str 要处理的字符串
* @return 处理后的字符串
*/
public static String rightTrim(String str) {
if (str == null) {
return "";
}
int length = str.length();
for (int i = length - 1; i >= 0; i--) {
if (str.charAt(i) != 0x20) {
break;
}
length--;
}
return str.substring(0, length);
}
  在上文中主要写的就是public static String[][] getxlsData(String file, int ignoreRows,String a)这个方法,这个方法中file是写excle的路径,ignoreRows是指excle中最上面起到提示作用的那几行,代码会直接忽略不读取,而a是字符串,是指在excle中指定的sheet页的名称,这样代码中就会只读取该sheet页的数据,可喜的是代码会把数据转化为二维数组,那正是我们在原有代码中所需要的数据结构啊
下图是文章中的excle的图片

  如上图的excle,到了代码里面就会变为一个3*5的2位数组形式,然后按照原先的初始化一样,即可完成初始化

    private int a;
private int b;
private int c;
private int d;
@Parameterized.Parameters
@SuppressWarnings("unchecked")
public static Collection zlrshiyan() throws IOException {
File file = new File("/Users/zlr/Desktop/TestAuto_Integration/ExcelDemo.xls");
Object[][] object = getxlsData(file, 0, "/a");
return Arrays.asList(object);
// return Arrays.asList(new Object[][]{{2,6},{3,5}});
}
public zlrshiyan(String b,String d,String e){
System.out.print(b+d+e);
this.b = Integer.parseInt(b);
this.d= Integer.parseInt(d);
System.out.print(b+d);
}
@Before
public void testinit() throws Exception{
a=1;
c=3;
}
@Test
public void test1() throws Exception{
Assert.assertEquals(a+b+c, d);
}
}
  在上文代码中object就是文件以a命名的sheet页所转化为的3*5的二维数组,然后就像之前一样的执行效果
  这样的代码是可以复用的,如何复用呢?说实话,有点low,后来我来到了大公司,学习了spring,学习了mybits,学会了从数据库中读取代码而非这种,从excle读取代码,不过换汤不换药,思路很相近,本文来用文字大致介绍一下我在上上家公司的工作成果和自动化思路
  在上文的代码中可以见到,已经将数据和代码执行逻辑分开了,那么实际上,如果某些代码的处理逻辑不同而数据数量和参数名等很相同,不同的只是参数值的话,那么可以使用一个excle的一个sheet页面来储存测试数据,而代码的处理逻辑是不变的~~这令我不禁想到了接口测试,同一个接口,往往参数设计和一些调用甚至返回断言逻辑是不变的,而变化的,往往是每次传进去的参数或者是接口启动的环境(线上,测试,甚至预发环境),这些有时候真的,比较适合而且本人实际验证了,可以使用上述代码来实现,也可以把数据载体换为数据库等,但是思路完全一样,一个sheet页其实就是数据库中的一张表啊,很相似的
  另一方面,我们会想到一个问题,那就是多个接口如何去做。由于每个接口传参数不同,而且每个接口的代码调用方法,校验逻辑也不尽相同,所以,不同接口之间的test往往不一样,导致一个class文件一个接口,而数据源头,不管是excle或者是数据库,设计的方案都是越简单越好的,所以往往也一样,是一个库一个sheet页一个接口,就像下图一样

  下面来讨论一下这一套框架吧

  我在多个公司搭建自动化工具,其中这个框架,基本上是接口自动化框架中我所用的主流框架,我所说的接口自动化,不是人来做的那种半自动化而是全自动化,当然,可以在这个框架基础上开发各种前端的代码,使得测试人员能使用非sql语句的方式,如页面点击等等方式修改文档中的数值以及sheet页等等,不过那些的本质思路都没变化,都是在这个框架上的拓展

  总的来说,这种数据驱动的自动化框架,从根本上解决了问题,如何去把代码和测试数据,分割开,使得测试人员或者其他人员,在接口逻辑不变的基础上,只需要通过一些方法,修改数据库或者文档就可以实现了对测试方式的控制,这真的是很不错的代码思维,而且,从根本上也方便了不懂代码的人执行自动化,直接降低了自动化的成本,但是,在我现在看来,其实实际上,往往公司的自动化是由少数几个同事搞起来的,而其他不懂代码的人根本不用,,,而且往往不懂代码的测试人员也没有那么强的上进心去懂代码,所以,我现在对所谓的让不会代码的人也来做自动化这个初衷表示怀疑,真的

  如果把初衷改为,让测试开发们,写出的自动化确实常常因为版本的更替而不适用需要修改,这时,自动化代码的开发者,流动性又很强,那么我们的代码,可读性真的,还不错其实,交接起来很容易,即便没有交接,新人来理解往往也很容易

  上述是杂谈,总之对于写一个接口自动化的后台代码而言,这一套代码,在实际运行中也遇到过各种各样的问题啊,,,下一篇文章会有所讲解的

												

java自动化-数据驱动junit演示,下篇的更多相关文章

  1. java自动化-数据驱动juint演示,上篇

    本文旨在帮助读者介绍,一般的全自动化代码接口,并简单介绍如何使用数据驱动来实现简单的自动化 在经过上述几个博客介绍后,相信读者对自动启动执行一个java编译过的class有了一定了解,也完全有能力去执 ...

  2. JAVA自动化之Junit单元测试框架详解

    一.JUnit概述&配置 1.Junit是什么? Junit是一个Java 编程语言的开源测试框架,用于编写和运行测试.官网 地址:https://junit.org/junit4/ 2.Ma ...

  3. java自动化-junit框架简述

    本人使用的是java的junit框架来组织的自动化测试,故我这边需要简单介绍一下junit框架 首先,建议自行百度一下junit框架,先有一个大概的了解 所谓的接口自动化测试,会对多个接口中每一个接口 ...

  4. Java单元测试框架 JUnit

    Java单元测试框架 JUnit JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于KentBeck的sUnit的xUnit家族中为最成功的一 ...

  5. Java单元测试之JUnit 5快速上手

    前言 单元测试是软件开发中必不可少的一环,但是在平常开发中往往因为项目周期紧,工作量大而被选择忽略,这样往往导致软件问题层出不穷.线上出现的不少问题其实在有单元测试的情况下就可以及时发现和处理,因此培 ...

  6. Jenkins CI&CD 自动化发布项目实战(下篇)

    Jenkins CI&CD 自动化发布项目实战(下篇) 作者 刘畅 时间 2020-12-04 实验环境 centos7.5 主机名 ip 服务配置 软件 gitlab 172.16.1.71 ...

  7. 《手把手教你》系列技巧篇(五十一)-java+ selenium自动化测试-字符串操作-下篇(详解教程)

    1.简介 自动化测试中进行断言的时候,我们可能经常遇到的场景.从一个字符串中找出一组数字或者其中的某些关键字,而不是将这一串字符串作为结果进行断言.这个时候就需要我们对字符串进行操作,宏哥这里介绍两种 ...

  8. 《手把手教你》系列技巧篇(六十一)-java+ selenium自动化测试 - 截图三剑客 -下篇(详细教程)

    1.简介 按照计划宏哥今天将介绍java+ selenium自动化测试截图操作实现的第三种截图方法,也就是截图的第三剑客 - 截取某个元素(或者目标区域)的图片.在测试的过程中,有时候不需要截取整个屏 ...

  9. java自动化-juint框架简述

    本人使用的是java的juint框架来组织的自动化测试,故我这边需要简单介绍一下juint框架 首先,建议自行百度一下juint框架,先有一个大概的了解 所谓的接口自动化测试,会对多个接口中每一个接口 ...

随机推荐

  1. SQL SERVER服务器登录名、角色、数据库用户、角色、架构的关系

    原创链接:https://www.cnblogs.com/junfly/articles/2798023.html SQL SERVER 基础教程中关于服务器登录名.服务器角色.数据库用户.数据库角色 ...

  2. webpack打包理解

    webpack打包理解(将所有依赖文件打包到一个文件中) 由于前端代码变得越来越多,越来越复杂, 纯粹脚本化的代码书写方式已经不能满足工程化得需求. 前端模块被抽象出来, 不仅仅包括js模块, 其它如 ...

  3. mongodb增加新字段报错解决方法

    今天想在项目的一个集合里增加一个新字段 db.article.update({},{$set:{status:0}},{multi:true}) multi : 可选,mongodb 默认是false ...

  4. 怎样解决canvas 插件 和html 页面中的事件冲突问题 ?

    很简单 ,在html 执行事件所在的div中 设置 position:relative;    

  5. luogu P5324 [BJOI2019]删数

    传送门 不如先考虑暴力,能删的序列首先有\(1,2,3...n\),还有就是升序排序后从后往前放数,第\(i\)位要么放\(i\),要么放\(i+1\)位置的数,例如\(1,2,4,4,5,6,9,9 ...

  6. Nginx开启gzip压缩解决react打包文件过大

    用create-react-app创建的react应用打包之后的build js有1M之多. 采用gzip打包传输,可以节约70%左右的带宽 nginx采用gzip打包方式 在nginx配置中添加如下 ...

  7. 利用request和re抓取猫眼电影排行

    import requests import re import time def get_one_page(url): headers = { 'User-Agent': 'Mozilla/5.0 ...

  8. 通过 iis或者本地IP 调试代码

    首先说下这个操作的意义,做微信开发每次需要将代码部署后才能调试.现在设置了Nginx服务器,生产环境可以指向正式服务器地址,调试时可以将Nginx指向自己的PC,但是vs调试启动的默认地址是[loca ...

  9. CentOS Android Studio桌面图标的创建

    1.切换到root用户,在桌面上创建Android.Studio.desktop,如下: [Desktop Entry] Name=Android Studio Comment=Android Stu ...

  10. python课程分享2-伊嬛

    2.4  模块 2.4.1  模块的概念 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,使用者可以把很多函数分组,分别放到不同 ...