博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
接口测试自动化框架搭建
阅读量:4982 次
发布时间:2019-06-12

本文共 5925 字,大约阅读时间需要 19 分钟。

经常,在应用程序的业务逻辑中存在大量的这样的接口:他们接受不同的输入,然后进行或验证,或处理,进而完成相同的流程。比如网站的登录入口,用户名和密码都有长度的限制,同时也具有是否允许特殊字符的限制等,所以在我们进行其单元的过程中,根据不同长度的用户名和密码,以及不同的字符组合,只需要提供相同的测试代码结构,就能完成测试,不同的仅仅测试数据与期望值,但是因为每一个测试方法中的输入参数不同,我们必须为每一个输入组编写单独的测试用例,从而产生大量冗余代码,十分不便于维护。幸好,本文所述的 Feed4JUnit 良好的解决了数据与代码分离的问题,Feed4JUnit是 JUnit测试框架的扩展,它通过操作来自于文件以及不同的数据源的测试数据,使您的单元测试变得更容易编写与维护。

 

使用工具

Eclipse++httpclient+feed4junit+Junit4

 

二、Feed4JUnit 的下载及安装

1. Feed4JUnit 是开源的测试组件,您可以从如下链接下载最新版本:

2. 解压下载的 zip包,复制整个 lib文件夹到您的 Java项目的根目录,如图 1:

图 1. 复制 lib 到项目根目录

 

3. 选定项目,右键选择项目的属性,然后通过 Add JARs将步骤 2中 lib 文件夹下的所有 Jar添加到项目的 BuildPath下,如图2

 

图 2. 添加 Jar 到 Build Path

 

三、使用 Feed4JUnit 实现数据与代码分离的测试

Feed4JUnit 的数据源可以包括以下几种类型-文件 (CSV或者Excel )、、自定义数据源。

Feed4JUnit使用一个特殊的运行类Feeder.class,用来支持与标识参数化测试,如果您想要编写数据与代码分离的测试脚本,必须在您的测试类上增加注释@RunWith(Feeder.class)。同时,您需要使用@Test来标示您实现测试的方法,并且使用@Source来声明和接收数据源的数据,基本的代码结构如清单3所示:

清单 3. 测试代码结构

package Living;

 

import static org.junit.Assert.*;

import org.databene.benerator.anno.InvocationCount;

import org.databene.benerator.anno.Source;

import org.junit.After;

import org.junit.AfterClass;

import org.junit.Before;

import org.junit.BeforeClass;

import org.junit.Test;

import org.junit.runner.RunWith;

 

import Pub.LivingPub;

import org.databene.feed4junit.Feeder;

 

@RunWith(Feeder.class)

public class PushTest{

 

    @BeforeClass

    public static void setUpBeforeClass()throws Exception {

    }

 

    @AfterClass

    public static void tearDownAfterClass()throws Exception {

    }

 

    @Before

    public void setUp() throws Exception {

    }

 

    @After

    public void tearDown() throws Exception {

    }

 

 

    @Test

//  @InvocationCount(1) //指定测试的次数

    @Source("D:/data/Living/push.xlsx")//指定测试的数据源

    public void pushTest(String cases,StringclassroomId,Stringname,

           String loginToken,StringquestionUrl,StringquestionId,Stringcorrect,

           String courseLevelId,Stringanswers,booleanexpected) {

          

        assertEquals(expected, LivingPub.push(cases,classroomId,name,loginToken,questionUrl,questionId,correct,courseLevelId,answers));

        }

   

}

 

以文件作为数据源

Feed4JUnit支持从 CSV或者 Excel文件里面读取数据作为输入,这里我们以Excel文件为例。

1. 在D:/data/Living/目录下创建push.xlsx数据文件,样例数据如图3,默认情况下,第一行会以列名存在,在运行过程中不会作为数据读取。

图 3. Excel 数据源

 

2. 创建测试类并在接收数据的测试方法上声明数据源为@Source("D:/data/Living/push.xlsx"),Excel中的数据在传递过程中会自动按照列与测试方法的参数的位置顺序进行匹配,并以行作为一个单位读取并传递给测试方法体。比如图3中的 cases列的值会做为方法的第一个参数传入方法体中,classroomId列的值会作为方法的第二个参数,以此类推。在测试进行过程中,首先在Excel文件中读取一行(包含三列),接着按照位置顺序将数据传递到方法体中(每列按顺序对应一个参数)进行执行,执行完成后读取Excel中的下一行进行相同流程的测试,其原理与Java中的迭代器十分类似。请注意当数据文件中数据的列数小于测试方法参数的个数的时候,测试会因为位置不匹配而失败。

 

3. 运行测试,因为 Feed4Junit是 JUnit的扩展,所以运行方式与 JUnit完全相同,即以 JUnit运行即可,运行结果如图 4所示,我们可以看到,Data.xls中的数据已全部传入测试方法并运行。

图 4. 运行结果示例

 

四、测试公共类及http模拟客户端实现

接口请求公共类及http模拟客户端:

 

1、 接口请求公共类代码:

public static boolean  push(String cases,String classroomId,String name,

String loginToken,String questionUrl,String questionId,String correct,
String courseLevelId,String answers) {
String url="xxxx";
Map<String, String> headers=new HashMap<String,String>();
Map<String, String> params=new HashMap<String,String>();
params.put("classroomId", classroomId);
params.put("name", name);
params.put("loginToken", loginToken);
JSONObject question=new JSONObject();
question.put("questionUrl", questionUrl);
question.put("questionId", questionId);
question.put("correct", correct);
question.put("courseLevelId", courseLevelId);
question.put("answers", answers);
params.put("question", question.toString());
String responseContent = PublicClient.getInstance().sendHttpGet(url, params,headers);
System.out.println(cases+"result:" + responseContent); 
JSONObject js=JSONObject.fromObject(responseContent);
String rscode=js.getString("code");
System.out.println(rscode);
//判断返回值
if (rscode.equals("10001"))
return false;
if (rscode.equals("10101"))
return false;
if (rscode.equals("10002"))
return false;
if (rscode.equals("10103"))
return false;
if (rscode.equals("10102"))
return false;
if (rscode.equals("10104"))
return false;
if (rscode.equals("11001"))
return false;
if (rscode.equals("11002"))
return false;
if (rscode.equals("999999"))
return false;
return true;
}

 

2、 模拟客户端代码:

public String sendHttpGet(String httpUrl,Map<String, String> params,Map<String, String> Headers) { 

// StringBuffer param = new StringBuffer();  
//        int i = 0;  
        if(params != null && !params.isEmpty()){
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
for(Map.Entry<String,String> entry : params.entrySet()){
String value = entry.getValue();
if(value != null){
pairs.add(new BasicNameValuePair(entry.getKey(),value));
}else {
pairs.add(new BasicNameValuePair(entry.getKey(),""));
}
}
try {
httpUrl += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, "UTF-8"));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
HttpGet httpGet = new HttpGet(httpUrl);
   if (Headers != null && !Headers.isEmpty()) {  
            for (Entry<String, String> entry : Headers.entrySet()) {  
            // 排除掉空值 
                if (entry.getValue() != null) {  
                httpGet.addHeader(entry.getKey(), entry.getValue()  
                            .toString());  
                } else {
                httpGet.setHeader(entry.getKey(), ""); 
            }  
        }
return sendHttpGet(httpGet);
}

 

 

 

 

/**

* 发送Get请求
* @param httpGet
* @return
*/
private String sendHttpGet(HttpGet httpGet) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
HttpEntity entity = null;
String responseContent = null;
try {
// 创建默认的httpClient实例.
httpClient = HttpClients.createDefault();
httpGet.setConfig(requestConfig);
// 执行请求
response = httpClient.execute(httpGet);
entity = response.getEntity();
responseContent = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭连接,释放资源
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseContent;
}

转载于:https://www.cnblogs.com/ceshi2016/p/6601917.html

你可能感兴趣的文章
写一篇博文介绍JSP
查看>>
C++笔记 3
查看>>
windows 2008 下C#调用office组件访问拒绝的解决方法(failed due to the following error: 80070005 拒绝访问)...
查看>>
golang-gin框架
查看>>
java程序中中常用到的linux操作
查看>>
asp.net的3个经典范例(ASP.NET Starter Kit ,Duwamish,NET Pet Shop)学习资料
查看>>
百度star2012初赛第一场的题目
查看>>
武汉第二十七天
查看>>
最长公共子序列
查看>>
MFC 鼠标去留
查看>>
怎么用xmind给自己制定计划目标
查看>>
word转PDF-jacob
查看>>
20条技巧,让Chrome超越Firefox
查看>>
正确释放WORD对象(COM组件) COMException: 被调用的对象已与其客户端断开连接
查看>>
Leetcode题解(一)
查看>>
SSIS报不能把DBNull convert成其他类型,Object等错误的解决办法
查看>>
【31】126. Word Ladder II
查看>>
Java反射基础
查看>>
List和Tuple的中的method对比
查看>>
关于ThreadLocal和一般的线程同步的详细解释
查看>>