java自动化-实际使用junit的演示

  本文简单介绍一下我写的http接口后端框架

  在经过之前多篇博客介绍之后,读者应掌握如下技能

1,自动运行一个或者多个junit框架编写的java代码

2,对数据驱动以及关键字驱动有一定的了解和认识,甚至可以编写简单代码

  怎么说呢,在这个基础上,实际上对代码的能力就会有一定提升了,但是在实际应用中,会面对一大波问题,笔者也并不指望能把所有的坑都说一遍,本文来简单说一下接口和我的自动化后端逻辑

  首先先说,各个大公司都有自己的各种方式的接口,分为提供给外部的接口和内部使用的rpc接口,这里不讨论rpc接口,而外部接口看,更多的恐怕是http接口和https接口,其中https接口,其本质就是http接口加密而成的,故本文,对http接口进行介绍

  在之前的博客中曾经简单介绍过http请求,http分为多种请求方式,但是在实际应用中,post请求的连接https://www.cnblogs.com/xuezhezlr/p/7685750.html,get请求的连接https://www.cnblogs.com/xuezhezlr/p/7667995.html,在上文中可以看到,http请求一般的会包含两部分,一部分是请求的url,另一部分是请求的参数集合,所以可以像上面两个一样,使用doPost(String url, Map parameterMap)与doGet(String url,Map parameterMap)来执行http请求,在一些公司,同一个接口甚至使用get或者post,传输相同的参数也可以发送过去并请求成功

  所以在代码中我们需要一大堆参数,和一个url,然后再进行断言和日志打印,先说说url,

  一般的url,分为域名和接口,比如本文网址https://www.cnblogs.com/xuezhezlr/p/9129026.html,其中www.cnblogs.com是域名,而后面的xuezhezlr/p/9129026.html是一个接口名,一般的公司呢,至少分为2套环境,一套测试环境一套正式环境(有的公司还会有预发环境),有时候都是相同域名不同host,所以在接口测试中不同接口之间,后面的接口名往往不一样,而域名往往是一样的,转换域名的实质是,在测试环境执行代码还是在正式环境执行代码,所以在代码中有必要把url分为两部分,一部分在每一个接口class中写,而另一部分域名则应该在公共方法中声明,或者在一个文件中写

  参数的话不用说了,可以参照之前的数据驱动博客

  断言的话,主要是对返回值进行断言,一般的公司返回值,每个接口都会有一个code或者retcode等参数,标志该接口请求是否成功,如code=0000代表成功,0001代表参数不全,9999代表接口内部异常等等,这部分返回码个人认为应该在设计用例时候预期到,比如这一条用例返回成功,少传一个参数会返回失败,所以,完全可以在参数化的文档中进行声明,而另一方面,每个接口除了会返回一个统一的标志位之外,还会返回一大堆其他的如json等等格式的字符串,这部分的话也不是不能在excle中填写,但是成本很大而且,不具有普遍性,我一般都是在代码中来编写的而非excle

  日志打印也很重要,在日志中要说明哪个接口哪一条用例执行成功或者失败,其实成功的话倒是无所谓,只需要最后能知道成功就行,失败的话需要在日志里面打印出来失败日志和返回值,以便在报告邮件中展示出来并让开发或者测试认识到,自动化测试最终结果,是说开发代码有变动导致接口异常呢,还是环境问题呢,还是测试代码问题?所以这部分也很重要,我是做在了excle或者数据库里面作为测试参数来看

  下面是没有使用excle或者数据库等数据驱动的一个实例

@Test
public void testsSuccessgetcode() throws Exception{
applyParams.put(PbgDict.TYPE, "sendmessage");
applyParams.put(PbgDict.mobile, mobile);
get("/app/getcode",applyParams,"正常用例","0");
}public void get(String url,Map parameterMap,String a,String errno1) throws Exception {
   System.out.println("==========get自动化测试" + url + a+"=========");
System.out.println("url:" + URI_BASE + url);
System.out.println("applyParams:" + parameterMap);
util.HttpUtil httpDoGet = new util.HttpUtil();
Map<String, Object> result = httpDoGet.doGet(URI_BASE + url, parameterMap);
System.out.println("result:" + result);
String errno = result.get(PbgDict.ERRNO).toString();
System.out.println("errno=" + errno);
System.out.println("------------------------------\n");
Assert.assertEquals(errno1, errno);
}
  上文中,代码中一个接口只需要传输4个参数,一个是url,一个是参数,一个是描述,一个是返回码,代码中会封装get和post两种请求,然后url会和URI_BASE 这个域名变量拼接出来完整的url,而参数会用来传递,描述用来打印日志,返回码的预期用来和实际的返回码比较来做断言,这样在每个接口的断言以及日志处理上可以做到相同的处理方式
这时候我做的数据驱动是形如这样的excle

  在上图中使用一个不同的sheet页来定义不同的接口,内容上第一列是预期返回码,第二列是描述,第三列以及后面的是传输的参数值
  这样写出来的代码,复用性较低,基本上每个接口都要单独写一套传参的方式,主要因为每个接口,有不同数量的入参,也有不同名称的入参,比如这个接口传输a=1,下个接口恐怕就要穿b=2了,当然,还有一个问题是维护成本,接口的参数方式和数量变化时候,由于参数化对列敏感,所以要对代码进行统一修改
  这时候我就在想,如何能够统一参数的数量和入参名称呢?在上上家公司,http请求大多是这样的参数形式,a=1&b=2&c=3这种,无论是get还是post,所以我看了http代码,
if(parameterMap.size()>0){
url_parameterMap = url +"?"+getMapString(parameterMap);
}
    public String getMapString(Map parameterMap) throws Exception{
StringBuffer mapStr = new StringBuffer();
Set set = parameterMap.keySet();
Iterator it = set.iterator();
int len = set.size();
System.out.println(len);
int n =1;
while(it.hasNext()) {
if(n != len) {
String str = it.next().toString();
String str_value = parameterMap.get(str).toString();
String str_map = str + "=" +URLEncoder.encode(str_value,charset);
mapStr.append(str_map);
mapStr.append("&");
}
if(len == n){
String str = it.next().toString();
String str_value = parameterMap.get(str).toString();
String str_map = str + "=" +URLEncoder.encode(str_value,charset);
mapStr.append(str_map);
}
++n;
}
return mapStr.toString();
}
  传进去的map最后还是会拼接成字符串,所以我不禁想,之前是map形式,我入参是多个,在get请求中我合并然后合而为一,如果说是我能在入参时候就合并为string的话,那么入参就是一个了,再把他们用来请求get,这样就能解决原有问题了
  所以另一方面我又封装了一种get请求
public void get(String url,String parameterMap,String a,String errno1) throws Exception {
System.out.println("==========get自动化测试" + url + a+"=========");
System.out.println("URI:" + URI_BASE + url);
System.out.println("applyParams:" + parameterMap);
util.HttpUtil httpDoGet = new util.HttpUtil();
Map<String, Object> result = httpDoGet.doGet(URI_BASE + url, parameterMap);
System.out.println("result:" + result);
String errno = result.get(PbgDict.ERRNO).toString();
System.out.println("errno=" + errno);
System.out.println("------------------------------\n");
Assert.assertEquals(errno1, errno);
}
实质上就是doget的两个不同的方法,一个传2个string,一个传一个string和一个map
public Map<String,Object> doGet(String url,String parameterMap) throws Exception {
String url_parameterMap = url;
url_parameterMap=url +"?"+parameterMap;
System.out.println("url_Get:" + url_parameterMap);
URL localURL = new URL(url_parameterMap);

URLConnection connection = openConnection(localURL);
HttpURLConnection httpURLConnection = (HttpURLConnection)connection;

httpURLConnection.setRequestProperty("Accept-Charset", charset);
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
if (httpURLConnection.getResponseCode() >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}

try {
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
reader = new BufferedReader(inputStreamReader);

while ((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine);
}
}
  这样做的好处在于,可以把参数请求时候不使用map而使用string了,然后现在的接口代码是这样的
public class test_ylw_app_config_discovery  extends PbgService {
Map<String, Object> applyParams = null;
private String miaoshu;
private String error;
private String value;
private static String key="/app/config/discovery";
@Parameterized.Parameters
@SuppressWarnings("unchecked")
public static Collection shiyan2() throws Exception {
File file = new File(postxlsapppath);
Object[][] object = getxlsData(file, 0, key);
return Arrays.asList(object);
}
public void initData() throws Exception {

applyParams = new HashMap<String, Object>();
}
@Before
public void setUp() throws Exception {
initData();
}
@After
public void TearDown() throws Exception {
this.applyParams.clear();
this.applyParams = null;
}
@AfterClass
public static void delete() {
supdelete();
}
public test_ylw_app_config_discovery(String error, String miaoshu, String value){
this.error = error;
this.miaoshu = miaoshu;
this.value=value;
}
@Test
public void testdiscovery() throws Exception{
value= supinit.zhuanhua2(value);
post(key,value,miaoshu,error);
}
}
  上述代码中,key是接口名,不同接口不一样,使用getxlsData方法读取指定excle中的指定sheet页key中的数据,然后再把参数部分合并,把excle原有的数据,分为3个参数,error,miaoshu和value,在每次执行的时候,由于是关键字驱动,使用supinit.zhuanhua2(value);来把value中的关键字转化为我们需要的数据再进行操作
  从上文代码看到,在最后接口自动化的代码已经能做到,所有的都很相近,只有key不同,其他参数以及处理+断言基本一样有一些读者可能要问,key也可以进入excle1啊,,,其实我写的数据库版本的驱动就是把key写到了excle里面,最后针对不同的key进行断言,大多数接口的话除了对基本的返回码做一个校验之外还需要对其他的,如数据库等等进行校验,所以很难写到一起
  总的来说,这就是我做的接口自动化了~~~感觉还很初级,需要提升啊,它对一个以http文明的小公司而言,已经是比较完整的了实际上








posted @ 2018-06-09 16:31  学者zlr  阅读(782)  评论(0编辑  收藏  举报