作者:软件质量保障
大家工作中统计测试用例、测试进度以及各种测试报表,或多或少离不开Excel,我们可以使用Excel公式实现自动化统计,当然也可以使用代码实现Excel数据的统计。
今天分享一款阿里巴巴开源的Excel解析工具EasyExcel,最后结合接口自动化实现一个自动化读取Excel测试用例并进行接口测试的项目。
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
为什么是EasyExcel?
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的Excel也不会出现内存溢出,让使用者更加简单方便。
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency>
官网:https://easyexcel.opensource.alibaba.com/
Github:https://github.com/alibaba/easyexcel
如何使用EasyExcel?
在介绍Excel的读取之前,我们需要了解下EasyExcel操作文件的步骤,以读Excel为例可以参考下面三个步骤:
1. 创建excel对应的实体对象
2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器
3. 直接读即可
如果我们的自动化框架设计思路是在Excel中保存我们的用例,那么假如用例内容包括以下内容。
我们首先新建一个TestCase类,只有四个字段:no、api、request、expect。
注意: Java类中的属性字段顺序和Excel中的表头字段顺序一致, 也可以不写@ExcelProperty
package cn.qa.excelUtil.entity;import com.alibaba.excel.annotation.ExcelProperty;import lombok.Data;@Datapublic class TestCase { // 根据Excel中指定列名或列的索引读取 @ExcelProperty(value = "no", index = 0) private String no; @ExcelProperty(value = "api", index = 1) private String api; @ExcelProperty(value = "request", index = 2) private String request; @ExcelProperty(value = "expect", index = 3) private String expect;}
另外写一个Excel文件统一存放路径的TestFileUtil,我们将测试Excel文件放到特定文件夹下面。
package cn.qa.excelUtil.util;import java.io.File;import java.io.InputStream;public class TestFileUtil { public static InputStream getResourcesFileInputStream(String fileName) { return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName); } public static String getPath() { return TestFileUtil.class.getResource("/").getPath(); } public static File createNewFile(String pathName) { File file = new File(getPath() + pathName); if (file.exists()) { file.delete(); } else { if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } } return file; } public static File readFile(String pathName) { return new File(getPath() + pathName); } public static File readUserHomeFile(String pathName) { return new File(System.getProperty("user.home") + File.separator + pathName); }}
读Excel
写法1:简单读Excel
// since: 3.0.0-beta1 String fileName = TestFileUtil.getPath()+ "demo" + File.separator + "TestCase.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 // 这里每次会读取100条数据 然后返回过来 直接调用使用数据就行 EasyExcel.read(fileName, TestCase.class, new PageReadListener<TestCase>(dataList -> { for (TestCase TestCase : dataList) { log.info("读取到一条数据{}", JSON.toJSONString(TestCase)); } })).sheet().doRead();
写法2:读取Excel数据并临时存储缓存
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "TestCase.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 EasyExcel.read(fileName, TestCase.class, new ReadListener<TestCase>() { /** * 单次缓存的数据量 */ public static final int BATCH_COUNT = 100; /** *临时存储 */ private List<TestCase> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); @Override public void invoke(TestCase data, AnalysisContext context) { cachedDataList.add(data); if (cachedDataList.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { saveData(); } private void saveData() { log.info("{}条数据,开始存储数据库!", cachedDataList.size()); log.info("存储数据库成功!"); } }).sheet().doRead();
写Excel
方法1:最简单的写法一,在已有Excel写入数据
package cn.qa.WriteExcelUtil;import cn.qa.excelUtil.entity.TestCase;import cn.qa.excelUtil.util.TestFileUtil;import com.alibaba.excel.EasyExcel;import java.io.File;import java.util.ArrayList;import java.util.List;public class WriteExcelUtil { public static List<TestCase> getTestCaseData(){ List<TestCase> testCases = new ArrayList<>(); for (int i = 1; i <= 10; i++) { TestCase testCase = TestCase.builder() .no(String.valueOf(i)) .api("api_" + String.valueOf(i)) .request("testRequest") .expect("success") .build(); testCases.add(testCase); } return testCases; } public static void main(String[] args) { String filename = TestFileUtil.getPath() + "demo" + File.separator + "TestCase.xlsx"; // 向Excel中写入数据 也可以通过 head(Class<?>) 指定数据模板 EasyExcel.write(filename, TestCase.class) .sheet("Case") .doWrite(getTestCaseData()); }}
方法2:最简单的写法二,新建Excel并写入
public static void main(String[] args) { String filename = TestFileUtil.getPath() + "demo" + File.separator + "TestCase.xlsx"; // 创建ExcelWriter对象 ExcelWriter excelWriter = EasyExcel.write(filename, TestCase.class).build(); // 创建Sheet对象 WriteSheet writeSheet = EasyExcel.writerSheet("Case").build(); // 向Excel中写入数据 excelWriter.write(getTestCaseData(), writeSheet); // 关闭流 excelWriter.finish(); }
结合自动化框架实现自动化测试
首先建议大家先看下这篇文章,《接口自动化框架脚手架-利用反射机制实现接口统一发起端》,而本期则是为接口的发起提供测试数据。
实现思路:读取Excel中的测试用例,通过接口的统一发起端调用接口,然后对接口返回信息作断言。
一、接口发起端Invoke代码如下(与之前的代码做了改动,即给invokeProxy增加返回值,因为后面要做断言):
import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Invoke { public Object invokeProxy(String serviceName, String api, String request) { try { Class<?> serviceClass = Class.forName(serviceName); Object service = serviceClass.getDeclaredConstructor().newInstance(); Method method = serviceClass.getMethod(api, String.class); return method.invoke(service, request); } catch (ClassNotFoundException e){ e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; }}
二、读自动化用例代码
package cn.qa.excelUtil;import cn.qa.excelUtil.entity.TestCase;import cn.qa.excelUtil.util.TestFileUtil;import com.alibaba.excel.EasyExcel;import com.alibaba.excel.read.listener.PageReadListener;import java.io.File;import java.util.ArrayList;import java.util.List;public class ReadCaseUtil { public static List<TestCase> readCase(String caseFile){ String fileName = TestFileUtil.getPath()+ "demo" + File.separator + caseFile; List<TestCase> result = new ArrayList<>(); // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 EasyExcel.read(fileName, TestCase.class, new PageReadListener<TestCase>(dataList -> { for (TestCase TestCase : dataList) { result.add(TestCase); } })).sheet().doRead(); return result; }}
三、开发用例
@Test public void testInvokeCase(){ String CreateServiceName = "cn.qa.reflect.demo.service.CreateService"; String QueryServiceName = "cn.qa.reflect.demo.service.QueryService"; // Step1: 读自动化用例 List<TestCase> testCaseList = ReadCaseUtil.readCase("TestCase.xlsx"); for (TestCase testCase: testCaseList){ if (testCase.getApi().equals("create")){ // Step2: 发起服务调用 Object response = invokeProxy(CreateServiceName, testCase.getApi(), testCase.getRequest()); // Step3: 断言 Assert.assertTrue(response.toString().contains(testCase.getExpect())); } if (testCase.getApi().equals("query")){ Object response = invokeProxy(QueryServiceName, testCase.getApi(), testCase.getRequest()); Assert.assertTrue(response.toString().contains(testCase.getExpect())); } } }
喜欢的话,就点个赞再走吧
标签:String,Excel,TestCase,用例,File,import,脚手架,public From: https://blog.51cto.com/u_15503184/5734114