自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)

一、概述

综述,本次做一个查询接口 的自动化测试案例,采用excel管理测试用例,ExtendReport呈现报告(前面有简单demo),Log4j记录日志(前面有简单demo),testng搭建测试框架。其中接口请求格式如下:

自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)_第1张图片

接口有数据时,返回如下:

自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)_第2张图片

 其中Table格式如下:

自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)_第3张图片

二、步骤 

1.新建Maven项目,引入操作Excel的jar包:


      org.apache.poi
      poi
      3.10-FINAL


     org.apache.poi
     poi-ooxml
     3.9
  

2.新建Excel工具类,ExcelUtil,代码如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelUtil {
	private static XSSFSheet ExcelWSheet;
	private static XSSFWorkbook ExcelWBook;
	private static XSSFCell cell;
	private static XSSFRow row;
	
	//设定要读写的Excel文件路径和文件名
	public static void setExcelFile(String path, String sheetName) throws Exception{
		
		FileInputStream excelFile = new FileInputStream(path);
		ExcelWBook = new XSSFWorkbook(excelFile);
		ExcelWSheet = ExcelWBook.getSheet(sheetName);
			
	}
	//读取Excel文件指定单元格,此函数只支持.xlsx的文件
	public static String getCellData(int rowNum, int colNum){
		System.out.println("1");
		//cell = ExcelWSheet.getRow(rowNum).getCell(colNum);
		row = ExcelWSheet.getRow(rowNum);
		if(!row.equals(null)) cell = row.getCell(colNum);
		System.out.println("2");
		String cellData = (String)(cell.getCellType() == XSSFCell.CELL_TYPE_STRING ? cell.getRichStringCellValue()+"": cell.getNumericCellValue());
		System.out.println("3");
		return cellData;
				
	}
	
	//在Excel文件的指定单元格写入数据,只能支持.xlsx的文件
	public static void setCellData(int rowNum, int colNum,String result,String filePath) throws Exception{
		row =ExcelWSheet.getRow(rowNum);
		cell = row.getCell(colNum,Row.RETURN_BLANK_AS_NULL);
		if(cell == null){
			cell = row.createCell(colNum);
			cell.setCellValue(result);
		}else{
			cell.setCellValue(result);
		}
		
		FileOutputStream fileOut = new FileOutputStream(filePath);
		ExcelWBook.write(fileOut);
		fileOut.flush();
		fileOut.close();
	}
	
	//从Excel文件获取测试数据的静态方法,返回二维数组对象
	public static Object[][] getTestData(String excelFilePath, String sheetName) throws IOException{
		File file = new File(excelFilePath);
		FileInputStream inputStream = new FileInputStream(file);
		Workbook Workbook = null;
		//获取文件名的扩展名
		String fileExtensionName = excelFilePath.substring(excelFilePath.indexOf("."));
		//.xlsx时实例化XSSFWorkbook对象;xls时实例化HSSFWorkbook
		if(fileExtensionName.equals(".xlsx")){
			Workbook = new XSSFWorkbook(inputStream);
		}else if(fileExtensionName.equals(".xls")){
			Workbook = new HSSFWorkbook(inputStream);
		}
		//生成sheet对象
		Sheet Sheet = Workbook.getSheet(sheetName);
		//获取sheet表的行数,行号和列号都是从0开始的
		int rowCount = Sheet.getLastRowNum() - Sheet.getFirstRowNum();
//		System.out.println("行数:"+rowCount+"最后一行行号:"+Sheet.getLastRowNum()+"第一行行号:"+Sheet.getFirstRowNum());
		//用来存放读取的数据,list对象
		List records = new ArrayList();	
		//使用两个for循环来读取表中所有数据,除第一行,第一行是标题
		for(int i=1;i getTestListData(String excelFilePath, String sheetName) throws IOException{
			File file = new File(excelFilePath);
			FileInputStream inputStream = new FileInputStream(file);
			Workbook Workbook = null;
			//获取文件名的扩展名
			String fileExtensionName = excelFilePath.substring(excelFilePath.indexOf("."));
			//.xlsx时实例化XSSFWorkbook对象;xls时实例化HSSFWorkbook
			if(fileExtensionName.equals(".xlsx")){
				Workbook = new XSSFWorkbook(inputStream);
			}else if(fileExtensionName.equals(".xls")){
				Workbook = new HSSFWorkbook(inputStream);
			}
			//生成sheet对象
			Sheet Sheet = Workbook.getSheet(sheetName);
			//获取sheet表的行数,行号和列号都是从0开始的
			int rowCount = Sheet.getLastRowNum() - Sheet.getFirstRowNum();
//			System.out.println("行数:"+rowCount+"最后一行行号:"+Sheet.getLastRowNum()+"第一行行号:"+Sheet.getFirstRowNum());
			//用来存放读取的数据,list对象
			List records = new ArrayList();	
			//使用两个for循环来读取表中所有数据,除第一行,第一行是标题
			for(int i=1;i

 在某路径下新建excel文件,建议为.xlsx的,文档内容如下(根据自己所要测试的接口调整):

自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)_第4张图片

3.新建两个对象类,一个是用来管理请求参数,一个用来管理接口返回的json数据(自己根据所测试接口添加),代码如下:

请求类:

​
public class I_kuaQuMenZhen {
	
	private Object sin;
	private Object servicecode;
	private Object authoucode;
	private Object action;
	
	
	public I_kuaQuMenZhen(){}
	
	public void setSin(Object sin){
		this.sin = sin;
	}
	public void setservicecode(Object servicecode){
		this.servicecode = servicecode;
	}
	public void setauthoucode(Object data){
		this.authoucode = data;
	}
	public void setaction(Object action){
		this.action = action;
	}
	
	
	public Object getSin(){
		return this.sin;
	}
	public Object getservicecode(){
		return this.servicecode;
	}
	public Object getauthoucode(){
		return this.authoucode;
	}
	public Object getaction(){
		return this.action;
	}
	
	public void getString(){
		System.out.println("sin:"+this.sin+"servicecode:"+this.servicecode+"authoucode:"+this.authoucode+"aciton:"+this.action);
	}
	
}

​

 接口返回类:

public class I_kuaQuMenZhenJiekouReturn {
	private Object AuthOUCode;
	private Object AuthOUName;
	private Object ExpiryDate;
	private Object InDate;
	private Object ServiceCode;
	private Object ServiceName;
	
	public void setAuthOUCode(Object AuthOUCode){
		this.AuthOUCode = AuthOUCode;
	}
	public void setAuthOUName(Object AuthOUName){
		this.AuthOUName = AuthOUName;
	}
	public void setExpiryDate(Object ExpiryDate){
		this.ExpiryDate = ExpiryDate;
	}
	public void setInDate(Object InDate){
		this.InDate = InDate;
	}
	public void setServiceCode(Object ServiceCode){
		this.InDate = ServiceCode;
	}
	public void setServiceName(Object ServiceName){
		this.ServiceName = ServiceName;
	}
	
	
	public Object getAuthOUCode(){
		return this.AuthOUCode;
	}
	public Object getAuthOUName(){
		return this.AuthOUName;
	}
	public Object getExpiryDate(){
		return this.ExpiryDate;
	}
	public Object getInDate(){
		return this.InDate;
	}
	public Object getServiceCode(){
		return this.ServiceCode;
	}
	public Object getServiceName(){
		return this.ServiceName;
	}
	public String toString(){
		return "";
	}
}

4.引入extendReport、Log4j、testng所需要的jar包,并新建extendReport的监听器类,Log4j的工具类及配置文件,步骤请参考前两章。

5.引入httpClient的jar包


    org.apache.httpcomponents
    httpclient
    4.5.6
 

由于接口请求和返回参数都是json格式,需要引入以下jar包:


    net.sf.json-lib
    json-lib
    2.4
    jdk15


    com.alibaba
    fastjson
    1.2.4

新建接口请求类,调用httpClient实现

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSONObject;

import duixiang.I_kuaQuMenZhen;
import uitl.ExcelUtil;
import uitl.Log;
/**
 * 
 * @author liususu
 * @category 跨区门诊查询接口
 *
 */

public class KuaQuMZ {
	

	private HttpPost post;
	private CloseableHttpClient httpClient;
	private JSONObject json;
	
	//直接指定excel行执行请求
	public JSONObject send_I_kuaQ(String path,String sheetName,int rowNum) throws Exception{
	
		try{
		String JsonReturn = new String();
		Log.info("开始读取Excel数据");
		I_kuaQuMenZhen sendParm = getParm(path, sheetName, rowNum);
		JSONObject bodyJsonParam = new JSONObject();
		bodyJsonParam.put("sin",sendParm.getSin());
		bodyJsonParam.put("servicecode",sendParm.getservicecode());
		bodyJsonParam.put("authoucode",sendParm.getservicecode());
		JSONObject headJsonParam = new JSONObject();
		headJsonParam.put("action",sendParm.getaction());
		JSONObject allJsonParam = new JSONObject();
		allJsonParam.put("body",bodyJsonParam);
		allJsonParam.put("head", headJsonParam);
		//创建请求对象
		post = new HttpPost("请求地址");
		httpClient = HttpClients.createDefault();
		//4.创建请求体
		//StringEntity---UrlEncodedFormEntity
		//参考地址https://blog.csdn.net/tb_520/article/details/80447794
        StringEntity entity = new StringEntity(allJsonParam.toString(),"utf-8");	       
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json");
        Log.info("请求参数:"+allJsonParam.toString());
        //5.设置请求参数
        post.setEntity(entity);       
        //6.开始执行请求
        Log.startTestCase("跨区门诊查询接口开始请求");
        HttpResponse response = httpClient.execute(post);
        // 7.保存接口返回的响应码
        int statusCode = response.getStatusLine().getStatusCode();
        if(statusCode != HttpStatus.SC_OK){
        	Log.error("请求错误码为: "+statusCode);
        	json = null;
        }else{
        	Log.info("请求正确响应码为: "+statusCode);
            //7.得到接口返回的响应体
            HttpEntity RespEntity = response.getEntity();
		    if (RespEntity != null) {
				JsonReturn = EntityUtils.toString(RespEntity, "UTF-8");
				Log.info("--------------------------------------");
				Log.info("Response content: " + JsonReturn);
				json = JSONObject.parseObject(JsonReturn);	
				Log.info("--------------------------------------");
				Log.endTestCase("跨区门诊查询接口结束");	
			}			
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally{  	
        if(post != null){
            try {
                post.releaseConnection();
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
	return json;
	}
	//使用dataprovider提供测试数据
	public JSONObject send_I_kuaQDataPro(Object[] parm) throws Exception{
		
		try{
		String JsonReturn = new String();
		Log.info("开始读取Excel数据");
		I_kuaQuMenZhen sendParm = getParmDataPro(parm);
		JSONObject bodyJsonParam = new JSONObject();
		bodyJsonParam.put("sin",sendParm.getSin());
		bodyJsonParam.put("servicecode",sendParm.getservicecode());
		bodyJsonParam.put("authoucode",sendParm.getservicecode());
		JSONObject headJsonParam = new JSONObject();
		headJsonParam.put("action",sendParm.getaction());
		JSONObject allJsonParam = new JSONObject();
		allJsonParam.put("body",bodyJsonParam);
		allJsonParam.put("head", headJsonParam);
		//创建请求对象
		post = new HttpPost("请求地址");
		httpClient = HttpClients.createDefault();
		//4.创建请求体
		//StringEntity---UrlEncodedFormEntity
		//参考地址https://blog.csdn.net/tb_520/article/details/80447794
        StringEntity entity = new StringEntity(allJsonParam.toString(),"utf-8");	       
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json");
       // Log.info("请求参数:"+allJsonParam.toString());
        //5.设置请求参数
        post.setEntity(entity);       
        //6.开始执行请求
        Log.startTestCase("跨区门诊查询接口开始请求");
        HttpResponse response = httpClient.execute(post);
        // 7.保存接口返回的响应码
        int statusCode = response.getStatusLine().getStatusCode();
        if(statusCode != HttpStatus.SC_OK){
        	Log.error("请求错误码为: "+statusCode);
        	json = null;
        }else{
        	Log.info("请求正确响应码为: "+statusCode);
            //7.得到接口返回的响应体
            HttpEntity RespEntity = response.getEntity();
		    if (RespEntity != null) {
				JsonReturn = EntityUtils.toString(RespEntity, "UTF-8");
				//Log.info("--------------------------------------");
				//Log.info("Response content: " + JsonReturn);
				json = JSONObject.parseObject(JsonReturn);	
				//Log.info("--------------------------------------");
				Log.endTestCase("跨区门诊查询接口结束");	
			}			
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally{  	
        if(post != null){
            try {
                post.releaseConnection();
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
	return json;
	}

	
	public I_kuaQuMenZhen getParm(String path,String sheetName,int rowNum) throws Exception{
	
			Object[][] data = ExcelUtil.getTestData(path, sheetName);
			I_kuaQuMenZhen demo1 = new I_kuaQuMenZhen();
			demo1.setSin(data[rowNum-2][1]);
			demo1.setservicecode(data[rowNum-2][2]);
			demo1.setauthoucode(data[rowNum-2][3]);
			demo1.setaction(data[rowNum-2][4]);	
//			demo1.getString();	
			return demo1;
		
	}
	
	public I_kuaQuMenZhen getParmDataPro(Object[] dataP) throws Exception{
				
		I_kuaQuMenZhen demo1 = new I_kuaQuMenZhen();
		demo1.setSin(dataP[1]);
		demo1.setservicecode(dataP[2]);
		demo1.setauthoucode(dataP[3]);
		demo1.setaction(dataP[4]);	
		return demo1;
	
	}
}

6.新建测试类,两种方式,一种是直接指定单元格读取数据,将每行数据写一个@Test方法,第二种使用@DataProvider和@Test实现。注意:excel数据表格的路径,请修改为自己的存放路径。

首先第一种,每行测试用例为一个测试方法,这种方式在报告中可以呈现自己写的测试备注。

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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import JiekouHttp.KuaQuMZ;
import duixiang.I_kuaQuMenZhenJiekouReturn;
import uitl.ExcelUtil;
import uitl.Log;





public class TestKuaQuMZ {
	@Test
	public void MaoYan(){
		KuaQuMZ kuaQ = new KuaQuMZ();
		
		try {
		//	kuaQ.getParm("E:\\测试1.xlsx","Sheet1",0);
			I_kuaQuMenZhenJiekouReturn returnDemo= new I_kuaQuMenZhenJiekouReturn();
			JSONObject parmReturn = kuaQ.send_I_kuaQ("E:\\测试1.xlsx", "Sheet1", 2);
			JSONObject bodyParm = (JSONObject)parmReturn.get("body");
			JSONArray bodyTableParm = (JSONArray)bodyParm.get("Table");
			String nameReturn = bodyParm.get("name").toString();
			ExcelUtil.setExcelFile("E:\\测试1.xlsx", "Sheet1");
			String assertDate  = ExcelUtil.getCellData(1, 5);
			//断言内容根据实际情况,判断用例是否执行成功
			Assert.assertEquals(assertDate, nameReturn);
                        //以上断言通过,则将excel文档中的“测试结果”置为“pass"
                        ExcelUtil.setCellData(1, 8, "pass", "E:\\测试1.xlsx");
    												
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void ExceptionMessage1(){
		
		KuaQuMZ kuaQ = new KuaQuMZ();
		
		try {
		//	kuaQ.getParm("E:\\测试1.xlsx","Sheet1",0);
			I_kuaQuMenZhenJiekouReturn returnDemo= new I_kuaQuMenZhenJiekouReturn();
			JSONObject parmReturn = kuaQ.send_I_kuaQ("E:\\测试1.xlsx", "Sheet1", 3);
			JSONObject bodyParm = (JSONObject)parmReturn.get("body");
			JSONArray bodyTableParm = (JSONArray)bodyParm.get("Table");
                        //注:本方法没有写断言和修改测试结果												
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Test
	public void ExceptionMessage2(){
		KuaQuMZ kuaQ = new KuaQuMZ();		
		try {
		//	kuaQ.getParm("E:\\测试1.xlsx","Sheet1",0);
			I_kuaQuMenZhenJiekouReturn returnDemo= new I_kuaQuMenZhenJiekouReturn();
			JSONObject parmReturn = kuaQ.send_I_kuaQ("E:\\测试1.xlsx", "Sheet1", 4);
			JSONObject bodyParm = (JSONObject)parmReturn.get("body");
			JSONArray bodyTableParm = (JSONArray)bodyParm.get("Table");
                        //注:本方法没有写断言和修改测试结果
                        //取接口返回的table中的数据值,存入对象
			for(int i=0;i

第二种,代码如下,这种方式遗留一个问题,在最后报告中会呈现。

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import JiekouHttp.KuaQuMZ;
import uitl.ExcelUtil;
import uitl.Log;

public class TestKuaQuMZDataProvider {
	
	
	@DataProvider(name="loginData")
	private Iterator LoginDataProvider() throws IOException {
	    List result=new ArrayList();
	    List data = ExcelUtil.getTestListData("E:\\测试1.xlsx", "Sheet1");
	    Iterator it=data.iterator();
	    while(it.hasNext()){
	    result.add(new Object[] { it.next() });
	    }
	    return  result.iterator();
	} 
	@Test(dataProvider = "loginData")
	public void testMaoyan(Object[] sendParm){
		KuaQuMZ kuaQ = new KuaQuMZ();
		try {
			kuaQ.send_I_kuaQDataPro(sendParm);
			Log.info("dataProvider");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

7.配置testng的xml,具体参考上上一篇。代码如下:

 针对第一个test类配置:






 
        
            
                
                    
                

            

        

    
     
        
            
                
                    
                    
                
            
        
    
   
    	
      

 针对第二个test类配置:




 
        
            
                
                    
                

            

        

    

   
    	
      

多个suite的配置:






  
        
        

        
        

  
   
    	
      

 

8.运行testSuite,查看报告

自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)_第5张图片

 

自动化测试:单个接口自动化测试简单案例(Maven+testng+HttpClient+Excel+Log4j+ExtendReport)_第6张图片 

 执行代码后,excel数据如下:

三、总结

1.本次采用的excel存放请求数据,断言关键字,测试结果,后续可与数据库进行结合,从数据库取出接口需要的请求参数,并且对于接口用例是否通过做的断言,也要与数据库存放的源数据进行比较。

2.对于很多接口,接口地址的配置,后期可采用配置文件来统一做全局变量,统一管理,方便修改

你可能感兴趣的:(自动化)