接口测试方案(接口测试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);
}
}
执行结果