本文旨在帮助读者介绍,如何使用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. IPv6 RIPng (PT)

    在Cisco路由器上配置RIPng  一.拓扑图 二.地址表 Device Interface IPv6 Address R1 F 0/0 2001:0DB8:CAFE:0001::1/64 S 0/ ...

  2. Windows Hook技术

    0x01 简介 有人称它为“钩子”,有人称它为“挂钩”技术.谈到钩子,很容易让人联想到在钓东西,比如鱼钩就用于钓鱼.编程技术的钩子也是在等待捕获系统中的某个消息或者动作.钩子的应用范围非常广泛,比如输 ...

  3. 毕业设计——Django邮件发送功能实现及问题记录

    django发送邮件:send_mail()&send_mass_mail() 自强学堂 刘江的博客 HTTPS,TLS和SSL django发送邮件及其相关问题 步骤 : 0. 登录作为发送 ...

  4. go之路

    目录 go初识[第一篇]初识 go初识[第二篇]包.变量.函数

  5. selenium + python自动化测试(一)

    本篇随笔为散集.不多逼逼直接干 step 1:使用webdriver调用浏览器,webdriver支持的浏览器为Firefox(),IE(),Chrome(),不同的浏览器需要安装不同的驱动. 本文使 ...

  6. java连接3种数据库 JdbcLinkDB --201801

    先看这篇记录 java连接3种数据库 JdbcLinkDB 测试 --201801 配置文件放在jar外面 读取,遇到的问题 - 海蓝steven - 博客园https://www.cnblogs.c ...

  7. United States Department of Agriculture 美国农业部网站数据自动下载小脚本

    帮对象写的自动点击页面的小脚本,如果有需要的可以试试,(#^.^#) https://apps.fas.usda.gov/gats/ExpressQuery1.aspx var year = '199 ...

  8. insert主键返回 selectKey使用

    有时候新增一条数据,知道新增成功即可,但是有时候,需要这条新增数据的主键,以便逻辑使用,再将其查询出来明显不符合要求,效率也变低了. 这时候,通过一些设置,mybatis可以将insert的数据的主键 ...

  9. mysql登录报错“Access denied for user 'root'@'localhost' (using password: YES”)的处理方法

    环境 CentosOS 6.5 ,已安装mysql 情景 root密码忘记,使用普通用户无法登录 解决 问题一 无法使用mysql命令 参考文章:https://www.cnblogs.com/com ...

  10. 从koa-session源码解读session本质

    前言 Session,又称为"会话控制",存储特定用户会话所需的属性及配置信息.存于服务器,在整个用户会话中一直存在. 然而: session 到底是什么? session 是存在 ...