接口测试方案(接口测试02)
接口测试方案(接口测试02)请求报文:请求行(请求方式、网址、协议版本)、信息头、消息体HTTP协议的报文系统内部的接口接口测试的意义安全性、执行效率、介入时间、稳定性
前情回顾什么是接口测试
基于HTTP协议,通过工具或者代码模拟请求,检查响应结果是否符合接口说明文档的一种测试
接口测试分类
系统对外的接口
系统内部的接口
接口测试的意义
安全性、执行效率、介入时间、稳定性
HTTP协议的报文
请求报文:请求行(请求方式、网址、协议版本)、信息头、消息体
响应报文:状态行(协议版本、状态码、状态名称)、信息头、消息体
如何做接口测试
找开发要接口说明文档
根据文档,设计测试用例
编写代码实现接口测试
定期执行接口测试代码
检查生成的测试报告
编写测试总结报告
通过HttpClient模拟get请求的代码
1.创建HttpClient
CloseableHttpClient client = HttpClients.creatDefault();
    
2.构建网址
URI uri = new URIBuilder()
  .setScheme("协议")
  .setHost("域名")
  .setPort(端口号)
  .setPath("路径")
  .setParameter("参数的键"  "参数的值")
  ......
  .build();
    
3.创建请求
HttpGet get = new HttpGet(uri);
    
4.执行请求,获取响应
CloseableHttpResponse response = client.execute(get);
    
5.检查响应结果
状态行
response.getStatusLine()
    
信息头
response.getAllHeaders()
    
消息体
response.getEntity()
练习
零七生活API - 提供免费接口调用平台(https://api.oick.cn/)

在众多接口中选择自己感兴趣的来试一试,编写接口代码
这里我以毒鸡汤为例

可以得到接口地址,请求方式等其他信息
代码如下
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.testng.annotations.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class DuJiTang {
    @Test
    public void testJiTang() throws URISyntaxException  IOException {
        CloseableHttpClient client = HttpClients.createDefault();
        //接口地址
        //https://api.oick.cn/dutang/api.php
        URI uri = new URIBuilder()
                .setScheme("https")
                .setHost("api.oick.cn")
                //端口号可省略不写
                //.setPort(443)
                .setPath("dutang/api.php")
                //没有需要输入的参数
                //.setParameter()
                .build();
        HttpGet get = new HttpGet(uri);
        CloseableHttpResponse response = client.execute(get);
        System.out.println(response.getStatusLine());
        Header[] headers = response.getAllHeaders();
        for (Header h : headers){
            System.out.println(h);
        }
        String responseText = EntityUtils.toString(response.getEntity());
        System.out.println(responseText);
    }
}
    
执行结果

POST请求
前面讲的是get请求,接下来讲post请求
get请求和post请求的区别
没有本质区别,只有协议约定的区别
1.参数位置不同:get请求的参数通过网址传递;post请求可以放在消息体中
2.安全性不同:对于用户来讲,post请求更安全,post请求的参数放在消息体中,可以更好的保护用户隐私;对于服务器来讲,get请求更安全,get请求一般用于查询操作,get请求天然幂等,不会为服务器引入脏数据
3.参数的长度限制不同:get请求的参数受限于浏览器的地址栏,一般在10kb左右:post请求可以认为没有长度限制
4.发包次数不同:get请求只需要发一次包给服务器;post请求需要发两次包,第一次发请求行和信息头,服务器会返回一个临时状态码100,第二次发送消息体,再从服务器得到最终状态码
5.手工操作的影响:get请求有历史记录;get请求可以保存到收藏夹中;点击浏览器的后退按钮,post请求会二次发送
常见的状态码
200:请求成功
301:永久重定向;希望用户以后采用新的网址,旧的网址即将过期
302:临时重定向;希望用户继续使用旧的网址
400:错误的请求;一般请求的信息头写错了
401:未认证;未登录
402:暂时未使用,预留以后使用
403:禁止访问;登录,但是没权限
404:未找到;路径错误
500:服务器内部错误
501:未实现
502:网关错误
503:服务器不可见
通过HttpClient模拟post请求
API数据接口_免费数据调用_API接口平台_API分类大全-聚合数据(https://www.juhe.cn/docs/index/otherid/1)
注册登录,获取自己的key
这里我以随机笑话接口为例,创建RandomJoke.java

1.创建一个HttpClient
CloseableHttpClient client = HttpClients.createDefault();
    

2. 构建网址
get请求推荐使用URI
post请求推荐使用String uri
String uri = " ";
    

3.创建请求
HttpPost post = new HttpPost(uri);
    

4. 把参数组合成列表
4.1创建一个新的,空的列表
List<NameValuePair> list = new ArrayList<NameValuePair>();
    
4.2为列表添加参数
list.add(new BasicNameValuePair("username" "123"))
list.add(new BasicNameValuePair("password" "123456"))
....
    

5. 把列表转成消息体的类型
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list);
    

6. 为请求设置消息体
post.setEntity(entity)
    

7. 执行请求,获取响应结果
CloseableHttpResponse response = client.execute(post)
    

8. 检查响应结果
String responseText = EntityUtils.toString(response.getEntity())
    

代码整合
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class RandomJoke {
    @Test
    public void testJoke() throws IOException {
        //创建HttpClient
        CloseableHttpClient client = HttpClients.createDefault();
        //构建网址
        String uri = "http://v.juhe.cn/joke/randJoke.php";
        //创建请求
        HttpPost post = new HttpPost(uri);
        //把参数组合成列表
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        list.add(new BasicNameValuePair("key" "              "));
        //把列表转成消息体
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list);
        //为请求设置消息体
        post.setEntity(entity);
        //执行请求,获取响应
        CloseableHttpResponse response = client.execute(post);
        //检查响应结果
        String responseText = EntityUtils.toString(response.getEntity());
        System.out.println(responseText);
    }
}
    
执行结果

练习
星座配对

代码如下
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
public class StarPair {
    @Test
    public void testStar() throws IOException {
        CloseableHttpClient client = HttpClients.createDefault();
        String uri = "http://apis.juhe.cn/xzpd/query";
        HttpPost post = new HttpPost(uri);
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        list.add(new BasicNameValuePair("key" "             "));
        list.add(new BasicNameValuePair("men" "双鱼"));
        list.add(new BasicNameValuePair("women" "巨蟹"));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list "UTF-8");
        post.setEntity(entity);
        CloseableHttpResponse response = client.execute(post);
        String responseText = EntityUtils.toString(response.getEntity());
        System.out.println(responseText);
    }
}
    
执行结果

接口关联
接口关联也叫接口依赖
例:要想调用<获取微信服务器IP地址>这个接口,那么要依赖于<获取access_token>这个接口的返回值。也就是说,我们必须先调用<获取access_token>,得到acces_token的之后,才能调用微信公众平台上的其他接口,那么,就可以说这两个接口有关联关系



实现步骤
打开pom.xml下载代码库
<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.79</version> 
</dependency>
    

代码
String responseText = EntityUtils.toString(response.getEntity()) 相当于 responseText = {"access_token":"ACCESS_TOKEN" "expires_in":7200};
1.把响应文本转成json对象
JSONObject json = JSONObject.parseObject(responseText);
    
2.根据固定不变的键"access_token" 提取动态变化的值"ACCESS_TOKEN"
    String ACCESS_TOKEN;
    ACCESS_TOKEN = json.getString("access_token");
    
3.指定两个接口的执行顺序
 @Test(dependsOnMethod="第一个方法名")
    
4.把access_token的值 传给第二个接口使用
    .setParameter("access_token"  ACCESS_TOKEN)
    
代码如下
import com.alibaba.fastjson.JSONObject;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.testng.annotations.Test;
import java.io.IOException;
public class WeiXinTest {
    String ACCESS_TOKEN;
    @Test
    public void getaccesstoken() throws IOException {
        //调用第一个接口 提取accesstoken的值  赋值给成员变量ACCESS_TOKEN
        CloseableHttpClient client = HttpClients.createDefault();
        String uri = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&"  
                "appid=             &secret=              ";
        HttpGet get = new HttpGet(uri);
        CloseableHttpResponse response = client.execute(get);
        String responseText = EntityUtils.toString(response.getEntity());
        //把responseText转成json对象
        JSONObject json = JSONObject.parseObject(responseText);
        //从json对象中根据固定的键"access_token"  取对应的值
        ACCESS_TOKEN = json.getString("access_token");
    }
    @Test(dependsOnMethods = "getAccessToken")
    public void getServerIPAddress() throws IOException {
        //使用access_token 获取微信服务器所有的Ip列表
        CloseableHttpClient client = HttpClients.createDefault();
        String uri = "https://api.weixin.qq.com/cgi-bin/get_api_domain_ip?"  
                "access_token="  ACCESS_TOKEN;
        HttpGet get = new HttpGet(uri);
        CloseableHttpResponse response = client.execute(get);
        String responseText = EntityUtils.toString(response.getEntity());
        System.out.println(responseText);
    }
}
    
执行结果

更直观的代码
import com.alibaba.fastjson.JSONObject;
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.testng.annotations.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class WeiXinTest2 {
    String ACCESS_TOKEN;
    @Test
    public void getAccessToken() throws URISyntaxException  IOException {
        //创建HttpClient
        CloseableHttpClient client = HttpClients.createDefault();
        //构建网址
        URI uri = new URIBuilder()
                .setScheme("https")
                .setHost("api.weixin.qq.com")
                .setPort(443)
                .setPath("/cgi-bin/token")
                .setParameter("grant_type" "client_credential")
                .setParameter("appid" "              ")
                .setParameter("secret" "                 ")
                .build();
        //创建请求
        HttpGet get = new HttpGet(uri);
        //执行请求
        CloseableHttpResponse response = client.execute(get);
        //检查响应是否正确
        //状态行
        System.out.println(response.getStatusLine());
        //信息头
        Header[] headers = response.getAllHeaders();
        for (Header h : headers){
            System.out.println(h);
        }
        //消息体
        String responseText = EntityUtils.toString(response.getEntity());
        System.out.println(responseText);
        //把响应文本转成json对象
        JSONObject json = JSONObject.parseObject(responseText);
        //根据键”access_token“,取对应的值
        ACCESS_TOKEN = json.getString("access_token");
    }
    @Test(dependsOnMethods = "getAccessToken")
    public void getServerIPAddress() throws URISyntaxException  IOException {
        //创建HttpClient
        CloseableHttpClient client = HttpClients.createDefault();
        //构建网址
        URI uri = new URIBuilder()
                .setScheme("https")
                .setHost("api.weixin.qq.com")
                .setPort(443)
                .setPath("/cgi-bin/get_api_domain_ip")
                .setParameter("access_token" ACCESS_TOKEN)
                .build();
        //创建请求
        HttpGet get = new HttpGet(uri);
        //执行请求,获取响应
        CloseableHttpResponse response = client.execute(get);
        //检查响应结果是否正确
        //状态行
        System.out.println(response.getStatusLine());
        //信息头
        Header[] headers = response.getAllHeaders();
        for (Header h : headers){
            System.out.println(h);
        }
        //消息体
        String responseText = EntityUtils.toString(response.getEntity());
        System.out.println(responseText);
    }
}
    
执行结果





