8-12接口测试进阶-1数据驱动
课程目录:
- 数据驱动
- 接口源码分析
- 从源码中解析接口信息
- Dubbo接口测试
- 接口持续集成
1. 数据驱动测试(Data-Driver Testing)
相同的测试脚本使用不同的测试数据执行,并完全分离了测试数据和测试行为,这样的设计模式叫做数据驱动。
TestNG实现测试驱动的两个关键注解:
- @DataProvider(推荐)
- @Parameters(参数存储在xml中,不够灵活)
2. DataProvider基础
2.1 使用DataProvider
数据类
package com.csj2018.testdata;
import org.testng.annotations.DataProvider;
public class TestData {
@DataProvider(name="car")
public static Object[][] createData(){
return new Object[][]{
{"明朝","王阳明"}
};
}
}
测试类
package com.csj2018;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DataProviderDemo {
/*
* 类中提供测试数据
*/
@DataProvider(name="car")
public Object[][] createData(){
return new Object[][]{
{"大众","帕萨特"},
};
}
@Test(dataProvider = "car")
public void testData1(String brand,String middleClassAuto){
System.out.println("@dataProvider 从本类中读取测试数据");
System.out.println("品牌:"+brand+"\t中级车:"+middleClassAuto);
}
@Test(dataProvider = "car",dataProviderClass = com.csj2018.testdata.TestData.class)
public void testData2(String dynasty,String famous){
System.out.println("@dataProvider 从数据类中读取测试数据");
System.out.println("朝代:"+dynasty+"\t人物:"+famous);
}
}
2.2 method定制
package com.csj2018.testdata;
import org.testng.annotations.DataProvider;
import java.lang.reflect.Method;
public class TestData {
@DataProvider(name="car")
public Object[][] createData(Method m){
if(m.getName().equals("testData2")){
return new Object[][]{
{"西汉","霍去病"}
};
}
return new Object[][]{
{"明朝","王阳明"}
};
}
}
package com.csj2018;
import org.testng.annotations.Test;
public class Demo1 {
@Test(dataProvider = "car",dataProviderClass = com.csj2018.testdata.TestData.class)
public void testData1(String dynasty,String famous){
System.out.println("非testData2方法");
System.out.println("朝代:"+dynasty+"\t人物:"+famous);
}
@Test(dataProvider = "car",dataProviderClass = com.csj2018.testdata.TestData.class)
public void testData2(String dynasty,String famous){
System.out.println("testData2方法");
System.out.println("朝代:"+dynasty+"\t人物:"+famous);
}
}
3. 使用Parameters
创建测试用例
package com.csj2018;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class TestParameters {
@Test
@Parameters({"province","city"})
public void testParameters(String province, String city){
System.out.println("@Parameters");
System.out.println("省份:"+province+"\t城市:"+city);
}
}
新建xml文件,用于传递参数,并执行用例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite" verbose="1">
<test verbose="2" preserve-order="true" name="lesson1"><!--测试名称-->
<classes>
<class name="com.csj2018.TestParameters"><!--测试类的路径-->
<parameter name="province" value="浙江" />
<parameter name="city" value="杭州" />
<methods>
<include name="testParameters"/>
</methods>
</class>
</classes>
</test>
</suite>
4. DataProvider扩展
数据通常存在文件中,如csv、Excel,和用例是完全分离的
4.1 CSV
csv文件src/test/java/com/csj2018/testdata/testforpeople.csv
阿里,马云
腾讯,马化腾
读取csv文件的工具类CsvReade.java
package testdata;
import org.omg.CORBA.OBJ_ADAPTER;
import org.testng.annotations.Test;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CsvReader {
public static Object[][] getTestData(String fileName) throws IOException{
List<Object[]> records = new ArrayList<Object[]>();
String record;
/**
* 设定UTF-8字符集,使用带缓冲区的字符输入流BufferedReader读取文件
*/
BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"UTF-8"));
/**
* 读取CSV文件的标题行(第一行),忽略
*/
file.readLine();
/**
* 遍历读取文件中除第一行外的其他所有行内容,并存储名为results的ArrayList中
* 每一个records中存储的对象为一个String数组
*/
while ((record = file.readLine()) != null){
String[] fileds = record.split(",");
records.add(fileds);
}
file.close();
/**
* 定义函数返回值,即Object[][]
* 将存储测试数据的list转换为一个Object的二维数组
*/
Object[][] result = new Object[(records.size())][];
for (int i = 0; i< records.size();i++){
result[i] = records.get(i);
}
return result;
}
}
用例CsvTestDemo.java
package com.csj2018.testcase;
import com.csj2018.utils.CsvReader;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.IOException;
public class CsvTestDemo {
@DataProvider(name="csv")
public Object[][] testData() throws IOException {
return CsvReader.getTestData("src/test/java/com/csj2018/testdata/testforpeople.csv");
}
@Test(dataProvider="csv")
public void test(String compay,String people){
System.out.println(compay+"\t"+people);
}
}
4.2 Excel
操作Excel使用支持的第三方库,如poi库
在其官方网站有很多示例代码,如Reading and Rewriting Workbooks
先导入依赖
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
4.2.1 按照官方示例,熟悉poi
package com.testerhome;
import org.apache.poi.ss.usermodel.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.*;
public class TestExcel {
@Test
public void test() throws Exception{
try(InputStream inp = new FileInputStream("car.xlsx")){
Workbook wb = WorkbookFactory.create(inp);
Sheet sheet = wb.getSheetAt(0);
Row row = sheet.getRow(0);
System.out.println(row.getCell(0)+"\t"+row.getCell(1));
Cell cell = row.getCell(2);
if(cell == null){
cell = row.createCell(3);
}
cell.setCellType(CellType.STRING);
cell.setCellValue("日本车");
try(OutputStream out = new FileOutputStream("car.xlsx")){
wb.write(out);
}
}catch (IOException e){
System.out.println("文件不存在");
}
}
}
#### 4.2.2 使用Excel数据源,编写用例
编写工具类
```#java
package com.util;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
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.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class ExcelReader {
static Workbook workbook;
public static Object[][] readExcel(String filename,String sheetName) throws Exception{
InputStream inputStream = new FileInputStream(filename);
String fileExtensionName = filename.substring(filename.lastIndexOf("."));
if(fileExtensionName.equals(".xlsx")){
workbook =new XSSFWorkbook(inputStream);
}else if(fileExtensionName.equals(".xls")){
workbook = new HSSFWorkbook(inputStream);
}else{
System.out.println("该文件不是Excel文件");
}
Sheet sheet = workbook.getSheet(sheetName);
System.out.println(sheet.getFirstRowNum()+" "+sheet.getLastRowNum());
int rowcount = sheet.getLastRowNum() - sheet.getFirstRowNum();
List<Object[]> records = new ArrayList<Object[]>();
for(int i=1;i<=rowcount;i++){
Row row = sheet.getRow(i);
String[] files = new String[row.getLastCellNum()];
for(int j=0;j<row.getLastCellNum();j++){
Cell cell = row.getCell(j);
files[j] = cell.getStringCellValue();
}
records.add(files);
}
Object[][] results = new Object[records.size()][];
for(int i=0;i<records.size();i++){
results[i]=records.get(i);
}
return results;
}
}
测试类,<font color="#FF0000"注意将Excel表恢复</font>
```#java
package com.testerhome;
import org.apache.poi.ss.usermodel.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.*;
public class TestExcel {
@DataProvider(name="excel")
public Object[][] testExcelData() throws Exception{
return ExcelReader.readExcel("car.xlsx","sheet1");
}
@Test(dataProvider = "excel")
public void testDataProvider(String brand, String car){
System.out.println("品牌:"+brand+"\t 车型:"+car);
}
}
#### 4.2.3 通过读取Excel,编写接口用例
```#java
@DataProvider(name="comment")
public Object[][] CommentData() throws Exception{
return ExcelReader.readExcel("comment.xlsx","sheet1");
}
@Test(dataProvider = "comment")
public void testComment(String id,String page,String code){
String url = "https://www.apiopen.top/satinCommentApi";
given().param("id",id).param("page",page).get(url).then().body("code",equalTo(code.substring(0,code.indexOf("."))));
}
```