Eclipse基于TestNG使用Excel文件导入的自动化接口测试项目执行maven test

本文任务

搭建一个以TestNG为测试框架,以Maven构建项目测试的demo项目,测试内容主要由Excel文件导入服务接口地址和请求体数据,最后将测试结果写入Excel文件。

依赖

主要依赖一下包:

  1. testng 测试框架
  2. fastjson 做字符串和json结构之间的转换
  3. gson 接收@RequestBody String xx, 提取xx
  4. jsonassert 比较两个json是否相同
  5. poi Java API To Access Microsoft Format Files
  6. maven-surefire-plugin 这个apache官网也说了
    在这里插入图片描述
    就是用来做单元测试的插件。

代码结构

在这里插入图片描述
重点关注标黄的代码及文件即可

相关代码文件

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.lzy.learning</groupId>
  <artifactId>proj-auto-api-test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>proj-auto-api-test</name>
  <url>http://maven.apache.org</url>
  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
  </properties>
  <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.16</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>	
		    <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.8.7</version>
        </dependency>
        <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.1.23</version>
</dependency>
    	<dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>2.8.5</version>
</dependency>
<dependency>
	<groupId>org.skyscreamer</groupId>
	<artifactId>jsonassert</artifactId>
	<version>1.2.0</version>
</dependency>
  </dependencies>
  <build>
        <testResources>
            <testResource>
                <directory>${project.basedir}/src/test/resources</directory>
            </testResource>
            <testResource>
                <directory>${project.basedir}/src/main/resources</directory>
            </testResource>
        </testResources>
        <plugins>
        <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-surefire-plugin</artifactId>
               <version>2.20.1</version>
               <configuration>
                   <forkCount>0</forkCount>
                   <testFailureIgnore>true</testFailureIgnore>
                   	<suiteXmlFiles>
                   					 		<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
					</suiteXmlFiles>
               </configuration>
           </plugin>
           </plugins>
</build>
</project>

MyExcelReader.java

package org.lzy.learning.proj_auto_api_test.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class MyExcelReader {
	
	private static final String EXCEL_XLS = "xls";
    private static final String EXCEL_XLSX = "xlsx";

    private static Workbook getWorkbok(File file) throws IOException{
        Workbook wb = null;
        FileInputStream in = new FileInputStream(file);
        if(file.getName().endsWith(EXCEL_XLS)){     //Excel 2003
            wb = new HSSFWorkbook(in);
        }else if(file.getName().endsWith(EXCEL_XLSX)){    // Excel 2007/2010
            wb = new XSSFWorkbook(in);
        }
        return wb;
    }
	
	public static void writeExcel(List<List<String>> dataList, String finalXlsxPath, String sheetName){
        OutputStream out = null;
        try {

        	File file=new File(finalXlsxPath); 

//			if(!file.exists())    
//			{    
//			    try {    
//			        file.createNewFile();    
//			    } catch (IOException e) {    
//			        // TODO Auto-generated catch block    
//			        e.printStackTrace();    
//			    } 
//			}
 
        	
            // 读取Excel文档
            File finalXlsxFile = file;
            Workbook workBook = getWorkbok(finalXlsxFile);
            // sheet 对应一个工作页
//            Sheet newSheet = workBook.createSheet();
            Sheet sheet = workBook.getSheet(sheetName);
            if (sheet == null) {
            	sheet = workBook.createSheet(sheetName);
            }
            

            CellStyle style_FAILED = workBook.createCellStyle();
            style_FAILED.setFillForegroundColor(IndexedColors.RED.getIndex());
            style_FAILED.setFillPattern(CellStyle.SOLID_FOREGROUND);
            CellStyle style_PASSED = workBook.createCellStyle();
            style_PASSED.setFillForegroundColor(IndexedColors.GREEN.getIndex());
            style_PASSED.setFillPattern(CellStyle.SOLID_FOREGROUND);
            

            //删除原有数据,除了属性列
            int rowNumber = sheet.getLastRowNum();
            for (int i = 1; i <= rowNumber; i++) {
                Row row = sheet.getRow(i);
                sheet.removeRow(row);
            }

            // 创建文件输出流,输出电子表格:这个必须有,否则你在sheet上做的任何操作都不会有效
            out =  new FileOutputStream(finalXlsxPath);
            workBook.write(out);

            //写一行
            for (int j = 0; j < dataList.size(); j++) {
                Row row = sheet.createRow(j);

                //写一列
                List<String> datas = dataList.get(j);
                for (int k=0; k<datas.size(); k++) {
            		Cell cell = row.createCell(k);
                    cell.setCellValue(datas.get(k));
                    if ( "FAILED".equals(datas.get(k)))
                    	cell.setCellStyle(style_FAILED);
                    if ("PASSED".equals(datas.get(k)))
                    	cell.setCellStyle(style_PASSED);
                    	
                }
            }

            // 创建文件输出流,准备输出电子表格:这个必须有,否则你在sheet上做的任何操作都不会有效
            out =  new FileOutputStream(finalXlsxPath);
            workBook.write(out);
            System.out.println("data exportation done!");
        } catch (Exception e) {
            System.out.println("manually creating a raw XLSX file is required!");
            e.printStackTrace();
        } finally{
            try {
                if(out != null){
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

	public static Map<String, List<List<String>>> excelFile2Map(String fileName){
		File excelFile = new File(fileName); 
	    XSSFWorkbook wb = null;
	    try {
	        wb = new XSSFWorkbook(new FileInputStream(excelFile));
	    } catch (IOException e) {
	        e.printStackTrace();
	    }
	    int numberOfSheets = wb.getNumberOfSheets();
	    Map<String, List<List<String>>> ml = new HashMap<String, List<List<String>>>();
	    
	    for (int x = 0; x < numberOfSheets; x++) {
	    	
	        XSSFSheet sheet = wb.getSheetAt(x);
	        String thisSheetName = sheet.getSheetName();
	        
	        int columnNum = 0;
	        if (sheet.getRow(0) != null) {
	            columnNum = sheet.getRow(0).getLastCellNum()
	                    - sheet.getRow(0).getFirstCellNum();
	        }
	        if (columnNum > 0) {
	        	List<List<String>> lr = new ArrayList<List<String>>();
	            for (Row row : sheet) {
	               List<String> singleRow = new ArrayList<String>();
	                int n = 0;
	                for (int i = 0; i < columnNum; i++) {
	                    Cell cell = row.getCell(i, Row.CREATE_NULL_AS_BLANK);
	                    switch (cell.getCellType()) {
	                        case Cell.CELL_TYPE_BLANK:
	                        	singleRow.add(null);
	                            break;
	                        case Cell.CELL_TYPE_BOOLEAN:
	                            singleRow.add(Boolean.toString(cell.getBooleanCellValue()));
	                            break;
	                        // 数值
	                        case Cell.CELL_TYPE_NUMERIC:
	                            if (DateUtil.isCellDateFormatted(cell)) {
	                                SimpleDateFormat sdf = null;
	                                if (cell.getCellStyle().getDataFormat() == HSSFDataFormat
	                                        .getBuiltinFormat("h:mm")) {
	                                    sdf = new SimpleDateFormat("HH:mm");
	                                } else {// 日期
	                                    sdf = new SimpleDateFormat("yyyy-MM-dd");
	                                }
	                                Date date = cell.getDateCellValue();
	                                
	                            } else {
	                                cell.setCellType(Cell.CELL_TYPE_STRING);
	                                String temp = cell.getStringCellValue();
	                                // 判断是否包含小数点,如果不含小数点,则以字符串读取,如果含小数点,则转换为Double类型的字符串
	                                if (temp.indexOf(".") > -1) {
	                                	singleRow.add(String.valueOf(new Double(temp)).trim());
	                                } else {
	                                    singleRow.add(temp.trim());
	                                }
	                            }
	                            break;
	                        case Cell.CELL_TYPE_STRING:
	                        	singleRow.add(cell.getStringCellValue().trim());
	                            break;
	                        case Cell.CELL_TYPE_ERROR:
	                        	singleRow.add("");
	                            break;
	                        case Cell.CELL_TYPE_FORMULA:
	                            cell.setCellType(Cell.CELL_TYPE_STRING);
	                            String temp = cell.getStringCellValue();
	                            // 判断是否包含小数点,如果不含小数点,则以字符串读取,如果含小数点,则转换为Double类型的字符串
	                            if (temp.indexOf(".") > -1) {
	                                temp = String.valueOf(new Double(temp))
	                                        .trim();
	                                Double cny = Double.parseDouble(temp);//6.2041
	                                DecimalFormat df = new DecimalFormat("0.00");
	                                String CNY = df.format(cny);
	                            } else {
	                            	singleRow.add(temp.trim());

	                            }
	                        default:
	                        	singleRow.add("");
	                            break;
	                    }
	                }
	                lr.add(singleRow);
	            }
	            ml.put(thisSheetName, lr);
	        }
	        
	    }
	    
	    return ml;
	}
	
}

WebRequest.java

package org.lzy.learning.proj_auto_api_test.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

import com.google.gson.Gson;

public class WebRequest {
	

	
	public static String sendRequest(String url, Object object) throws Exception {
		PrintWriter out = null;
		BufferedReader in = null;
		StringBuilder result = new StringBuilder();
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			conn.setConnectTimeout(1000000);
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "application/json");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent","Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			conn.setRequestProperty("Content-Type","application/json;charset=utf-8");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(object);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
			result.append(line);
			}
		} catch (Exception e) {
			
			e.printStackTrace();
			throw new Exception("发送 POST 请求出现异常!" + e);
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result.toString();
	}
}

App.java

package org.lzy.learning.proj_auto_api_test;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
    
    public String sayHello() {
    	return "hellolzy";
    }
}

MainTest.java

package org.lzy.learning.proj_auto_api_test;

import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class MainTest {
	private App app;
	
	@BeforeMethod
	public void init() {
		app = new App();
	}
	
	@Test
	public void testSayHello() {
		Assert.assertEquals(app.sayHello(), "hellolzy");
	}

}

Run1Test.java

package org.lzy.learning.proj_auto_api_test;

import java.io.File;
import java.io.FileNotFoundException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.lzy.learning.proj_auto_api_test.util.MyExcelReader;
import org.lzy.learning.proj_auto_api_test.util.WebRequest;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import com.alibaba.fastjson.JSON;

public class Run1Test {
	
	private List<List<String>> responsePOST = new ArrayList<List<String>>();
	private List<List<String>> comparisonContent = new ArrayList<List<String>>();
	private int passCounter = 0;
	private int failedCounter = 0;
	private String inFilePath = "";
	private String outFilePath = "";
	
	private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");//设置日期格式
	private String startTime = "";
	private String endTime = "";
	
	@BeforeTest
	@Parameters(value={"WORKBOOKDIR", "OUTPUTFILEDIR"})
	public void checkFilesAvailable(String inputFilePath, String outputFilePath) throws FileNotFoundException {
		
		File in = new File(inputFilePath);
		if (!in.exists())
			throw new FileNotFoundException("input file is not found.");
		File out = new File(outputFilePath);
		if (!out.exists())
			throw new FileNotFoundException("output file is not found.");
		inFilePath = inputFilePath;
		outFilePath = outputFilePath;
		startTime = df.format(new Date());// new Date()为获取当前系统时间
		
	}
	
	@DataProvider(name="workBookData")
    public Iterator<Object[]> provideData() {

    	List<Object[]> testData = new ArrayList<Object[]>();

    	//fetch input data from XLSX file
    	Map<String, List<List<String>>> inputData = MyExcelReader.excelFile2Map(inFilePath);
    	List<List<String>> dataRows = inputData.get("input");
    	
    	//remove table header
    	dataRows.remove(0);
    	
    	for (List<String> rowRecord : dataRows) {
    		
			String ip_addr = rowRecord.get(2);
    		String port = rowRecord.get(3);
    		String service_route = rowRecord.get(4);
    		String sendObjStr = rowRecord.get(5);
    		
    		Map<String, String> reqMap = JSON.parseObject(sendObjStr, Map.class);
    		String url = ip_addr + ":" + port + service_route;
    		testData.add(new Object[] {rowRecord.get(0), rowRecord.get(1), url, reqMap, rowRecord.get(6)});
    	}
        return testData.iterator();
    }
    
//    @Test(dataProvider="workBookData")
    public void apiTestNoCompare(String testId, String testCase, String url, Map<String, String> reqBody) throws Exception {
    	
    	String resp = null;
    	try {
    		resp = WebRequest.sendRequest(url, reqBody);
    	}catch(Exception e) {
    		throw new Exception("apiTest METHOD failed: " + e);
    	}
//    	System.out.println(resp);
    	responsePOST.add(Arrays.asList(testId, testCase, resp));
    	
    }
    
    @Test(dataProvider="workBookData")
    public void apiTestWithCompare(String testId, String testCase, String url, Map<String, String> reqBody, String base_response) throws Exception {
    	
    	String resp = null;
    	try {
    		resp = WebRequest.sendRequest(url, reqBody);
    	}catch(Exception e) {
    		throw new Exception("apiTest METHOD failed: " + e);
    	}
//    	System.out.println(resp);
    	responsePOST.add(Arrays.asList(testId, testCase, resp));
    	JSONCompareResult result = JSONCompare.compareJSON(base_response, resp, JSONCompareMode.NON_EXTENSIBLE);
    	if (result.passed()) {
    		comparisonContent.add(Arrays.asList(testId, testCase, "PASSED", resp));
    		comparisonContent.add(Arrays.asList("", "", "", base_response));
    		passCounter += 1;
    	}else {
    		comparisonContent.add(Arrays.asList(testId, testCase, "FAILED", resp));
    		comparisonContent.add(Arrays.asList("", "", "", base_response));
    		failedCounter += 1;
    	}
    }
    
    @AfterTest
    public void doFinal() throws ParseException {
//    	for (List<String> l : testResult) {
//    		System.out.println(l.toString());
//    	}
    	float coverage = passCounter * 100.0f / (passCounter + failedCounter);
    	DecimalFormat decimalFormat = new DecimalFormat(".00");
    	//format 返回的是字符串
    	String percentage = decimalFormat.format(coverage);
    	comparisonContent.add(Arrays.asList("测试结果", percentage, "%", ""));
    	
    	
        endTime = df.format(new Date());// new Date()为获取当前系统时间
        String lapse =  String.valueOf(df.parse(endTime).getTime() - df.parse(startTime).getTime());
        responsePOST.add(Arrays.asList("测试开始时间", startTime));
        responsePOST.add(Arrays.asList("测试结束时间", endTime));
        responsePOST.add(Arrays.asList("测试耗时", lapse, "ms"));
        comparisonContent.add(Arrays.asList("测试开始时间", startTime));
        comparisonContent.add(Arrays.asList("测试结束时间", endTime));
        comparisonContent.add(Arrays.asList("测试耗时", lapse, "ms"));
        
    	MyExcelReader.writeExcel(responsePOST, outFilePath, "response");
    	MyExcelReader.writeExcel(comparisonContent, outFilePath, "comparison");
    }

}

TestMain2.java

package org.lzy.learning.proj_auto_api_test;

import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class TestMain2 {
	private App app;
	
	@BeforeMethod
	public void init() {
		app = new App();
	}
	
	@Test
	public void testSayHello() {
		Assert.assertEquals(app.sayHello(), "hellolzy");
	}
}

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >

<suite name="testALL" verbose="2" parallel="false">
<parameter name="WORKBOOKDIR" value="X:/data.xlsx"/>
<parameter name="OUTPUTFILEDIR" value="X:/result.xlsx"/>
<test name="test1">

        <classes>
            <class name="org.lzy.learning.proj_auto_api_test.Run1Test" />
            <class name="org.lzy.learning.proj_auto_api_test.MainTest" />
            <class name="org.lzy.learning.proj_auto_api_test.TestMain2" />
        </classes>

    </test>

</suite>

实践总结

  1. 特别注意下面的pom内容不要忘了加,然后testng.xml的路径不要搞错了。
 <plugins>
        <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-surefire-plugin</artifactId>
               <version>2.20.1</version>
               <configuration>
                   <forkCount>0</forkCount>
                   <testFailureIgnore>true</testFailureIgnore>
                   	<suiteXmlFiles>
                   					 		<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
					</suiteXmlFiles>
               </configuration>
           </plugin>
           </plugins>
  1. 这份代码,需要有X:/data.xlsx和X:/result.xlsx这两个文件,其中result.xlsx是手动新建的,里面不需要有内容,路径/名字对就行。data.xlsx文件内容如下
    在这里插入图片描述
    注意是在Input这个sheet名下噢。
  2. 最后还需要起一个后端把excel里的那些服务接口运行起来。
  3. 上述代码文件都安排好之后,用命令行在项目根目录下maven test一下,感受build success的快乐吧。
  4. 测试方法里面会对比实际请求的返回json数据和理论json进行比较。结果展示一下:
    在这里插入图片描述
  5. 最后在cmd里边,cd到项目根路径,
mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testng.xml -Dsurefire.forkCount=1 -Dsurefire.reuseFork=false

THANK YOU

有什么问题欢迎留言探讨哈,我会来看滴。谢谢大家

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值