Rest_Assured接口测试学习汇总

Rest_Assured接口测试学习

本文主要是本人学习并记录Rest_Assured测试框架的一些用法

学习过程中使用的是jdk15 maven3.8.6 以及 idea2022.2

mvn仓库地址:https://mvnrepository.com/



前言

rest_assured测试框架是用来进行resful服务接口测试的,该框架简化了resful服务的接口测试,支持post get delete options等请求,并对响应体进行断言,支持json xml yaml excel csv等文件的结构化解析,支持 xpath jsonpath gpath等的元素定位,支持Spring,符合契约变成思想(浅谈契约式变成
rest_assured 官方网站: https://rest-assured.io/
本文基于Junit5,学习rest_assured测试框架


一、基本用法

使用rest_assured需要引入其依赖,如下所示,将其复制到pom.xml,其中的版本号根据自己的要求填写,建议使用比较新的版本,不清楚版本号,需要使用上方mvnrepository官网地址进行搜索rest-assured

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>4.5.1</version>
    <scope>test</scope>
</dependency>

下面进行一个简单的get请求和post请求,restAssured主要是分为3大方法

given():设置头信息(header)设置请求参数(param,body)等
when():用来声明请求的方式(post get)和请求接口url
then():用来解析响应结果和断言(断言状态码,body体)

引入的包一定要是static修饰的静态包:import static io.restassured.RestAssured.given;

import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

/**
 * rest-assured基本用法
 */
public class RestAssuredTest {
    /**
     * given:设置测试预设(请求头、请求参数、请求体等)
     * when:想要执行的请求动作 get post
     * then:解析结果 断言
     * log().all()打印全部的相应信息
     * statusCode 断言状态码
     * body()断言返回的body种的信息
     */
    @Test
    void testGet() {
        String url = "https://httpbin.ceshiren.com/get";
        given()
                .param("key", "value")//添加请求参数
                .when()
                .get(url)
                .then()
                .log().all()
                .statusCode(200)//断言状态码
                .body("origin",is(equalTo("172.17.56.110")));
    }

    @Test
    void testPost() {
        String url = "https://httpbin.ceshiren.com/post";
        given().
                queryParam("key","value").//参数
                when().post(url).
                then().log().all().statusCode(200);
    }
}

二、参数化

在日常进行http接口测试时,知道,参数有很多种类型,以postman为例,body可以传输多种格式的参数,例如 xml json text 等
在这里插入图片描述

1.k-v型参数

get请求支持的参数类型为 key-value类型,可以将参数写在url上,也可以在写在queryparam上
post请求 也支持key-value,但是其请求参数是写在body体或者header中

传输单个参数可以使用param(key,value),传输多个参数,可以写多个param(key,value),或者使用params(k1,v1,k2,v2,…)
queryParam()方法与param方法用法类似

 given()
     .param("key", "value")//添加请求参数
     .param("key2", "value2")//添加请求参数
     //queryParam("key", "value")
     //params("key","v","key2","v2")
 .when()
      .get(url)
 .then()
     .log().all()
     .statusCode(200)//断言状态码

2.body数据

post大部分是使用body传输参数,因此given()中使用body()方法

  • json格式数据
    josn格式数据,一般在测试过程中是通过读取json文件、序列化结构体或者使用同样是k-v结构的map 来得到json
    这里需要传入content-type:application/json,来声明是json结构数据
	@Test
	//序列化结构体为json
    public void JsonTest() {
        Student stu = new Student("小明", 25, "24班", 24, 2401);
        String str = JSON.toJSONString(stu);
        given().contentType("application/json")
                .body(str)
                .log().body()
                .when().post(url)
                .then().log().all();
    }

    @Test
    //传输map
    public void MapJsonTest() {
        HashMap<String, String> map = new HashMap<>();
        map.put("name","美美");
        map.put("age","12");
        given()
                .contentType("application/json")
                .body(map)
                .when()
                .post(url)
                .then().log().all();
    }
  • xml格式数据
    xml类型的数据,一般是通过读取xml文件来获取的,xml是一种标记型语言,通常用来定位元素例
    xml型数据的用法,参考的是W3C里一个计算器的例子:http://dneonline.com/calculator.asmx
    在resources文件下创建一个xml文件并引入下面内容
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <Add xmlns="http://tempuri.org/">
            <intA>1</intA>
            <intB>1</intB>
        </Add>
    </Body>
</Envelope>

引入xml需要使用File读取xml文件内容,并声明content-type为text/xml类型,再将参数传入body()

import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import static io.restassured.RestAssured.given;

/**
 * xml格式的参数
 */
public class RestAssured3Test {
    String url = "http://dneonline.com/calculator.asmx";

    @Test
    public void testXml() {
        //定义请求体数据 xml
        try {
            File file = new File("src/test/resources/param.xml");
            FileInputStream fis = new FileInputStream(file);
            String str = IOUtils.toString(fis, "UTF-8");
            given()
                    .contentType("text/xml")
                    .body(str)
                    .when()
                    .post(url)
                    .then().log().all().statusCode(200);
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}


3.form

post请求可以通过提交form表单的形式提交请求参数,这里使用given().formParams()方法来设置参数,formparams可以设置多个参数
formParam()用来设置单个参数

import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;

/**
 * post请求
 */
public class FormTest {
    String url = "https://httpbin.ceshiren.com";

    @Test
    void form() {
        given()
                //.formParam("key1","value1")
                .formParams("key1", "value1", "key2", "value2")
                .log().headers()
                .log().body()
                .when()
                .post(url + "/post")
                .then()
                .log().body()
                .statusCode(200);
    }
}

三、定位响应元素并断言

测试一个接口有没有达到预期,需要进行响应的断言,这里有几种断言方式,如果返回的body是json类型可以使用rest_assurd自带或者jsonpath进行元素定位,如果返回的是xml类型则需要使用Xpath进行元素定位,定位到元素后使用assert或者hamcrest进行断言(junit5断言方式

1. restassured 自带json提取元素方式

rest_assured测试框架自带提取json元素的方法(测试中比较常用的就是自带的方式),使用"."来定位元素并提取元素值,然后使用assert进行断言

@Test
    public void jsonResp1() {
        String resp = given()
                .header("Hello", "world")
                .when()
                .get(url + "/get")
                .then()
                .log().all()
                .statusCode(200)
                .extract().response().asString();//提取响应的文本
        String str = from(resp).getString("headers.Hello");//提取 headers下面的hello的值,值就是前面写的 world
        assertEquals("world",str);

    }

2. jsonpath查找元素

jsonpath断言元素需要引入jsonpath依赖到pom.xml中

        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>2.6.0</version>
        </dependency>

可以使用这个地址进行练习定位json:http://jsonpath.com/
基本使用规则如下:
在这里插入图片描述

使用jsonpath定位元素的常用用法如下图
在这里插入图片描述

提取到元素后使用hamcrest匹配器进行断言

    @Test
    public void JsonPathTest() {
        String resp = given().header("Hello", "world")
                .when().get(url + "/get")
                .then()
                .log().all().statusCode(200)
                .extract().response().asString();
        String str = JsonPath.read(resp, "$.headers.Hello");//读取json中 headers下的hello
        assertThat("world", is(equalTo(str)));
    }

3. Xpath查找元素

xpath 查找元素的规则如下几种:

在这里插入图片描述

 @Test
    public void testXml() {
        //定义请求体数据 xml
        try {
            File file = new File("src/test/resources/param.xml");
            FileInputStream fis = new FileInputStream(file);
            String reqBody = IOUtils.toString(fis, "UTF-8");
            given()
                    .contentType("text/xml")
                    .body(reqBody)
                    .when()
                    .post(url)
                    .then()
                    .log().body()
                    .statusCode(200)
                    .body("//AddResult.text()", equalTo("2")); //响应断言
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

  • json schema
    使用json schema方式一般是用来断言整个响应的body体是否符合预期,首先是先制定一个预期的响应body体的内容和结构,使用json schema在线工具:https://app.quicktype.io/ 将预期的body体生成 json schema,如下所示:
    在这里插入图片描述
    在resources下创建一个schema.json文件将生成的json schema代码复制其中,增加使用json schema的依赖到pom.xml
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>4.4.0</version>
    <scope>test</scope>
</dependency>

然后发起请求,断言整个响应体

    @Test
    public void JsonSchema(){
        given()
                .when()
                .get(url+"/get")
                .then()
                .log().all()
                .statusCode(200)
                //.extract().response().asString();
                .assertThat()
                //根据schema中的的数据断言resp body是否与匹配
                .body(matchesJsonSchemaInClasspath("schema.json"));

    }

四、设置请求代理

在日常工作中很多时候不能直接访问请求地址,而是需要访问代理地址,因此我们使用配置本地代理的方式来学习如何配置代理
使用工具Charles设施本地代理端口(配置代理),开启一个localhost:8888的本地代理,所有的请求都会经过代理服务

1. http请求设置代理

代码中,在given()中使用proxy()方法进行代理配置,代码如下,是进行的http请求的代理配置

import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;

/**
 * http请求增加代理
 */
public class ProxyTest {
    String url = "http://httpbin.org.com";
    String proxyAddr = "127.0.0.1";
    int proxyPort = 8888;
    @Test
    //代理是在given中增加
    public void httpProxy() {
        given()
                .proxy(proxyAddr,proxyPort)
                .when()
                .get(url + "/get")
                .then()
                .log().all()
                .statusCode(200);

    }
}

2. https请求设置代理

https的代理与http有所不同,https比http多一个安全认证证书,因此直接访问https会报一个ssl的错误,因此要在代码中声明 忽略证书校验
	@Test
    //使用given内置的配置代理方法
    public void httpsProxy() {
        given()
                .proxy(proxyAddr, proxyPort)
                .relaxedHTTPSValidation()//忽略https证书校验
                .when()
                .get("https://httpbin.ceshiren.com/get")
                .then().log().all()
                .statusCode(200);
    }

3. 全局代理

上面的方法是使用的given()中的proxy()方法,这种方法有一个缺点,就是每一个请求都需要设置一遍代理,因此引入了另一种代理方式,设置全局代理

 @Test
    //创建静态的代理方法
    public void httpsProxy2() {
        RestAssured.proxy = host(proxyAddr).withPort(proxyPort);
        //忽略 tls 证书校验
        RestAssured.useRelaxedHTTPSValidation();
        given()
                //.proxy(proxyAddr, proxyPort)
                //.relaxedHTTPSValidation()//忽略https证书校验
                .when()
                .get("https://httpbin.ceshiren.com/get")
                .then().log().all()
                .statusCode(200);
    }

五、headers

1.自定义header内容

使用given().headers()方法添加header:
headers中包含:user-agent,content-type、data、encoding、connection等信息,headers信息是可以自定义的
以user-agent为例,user-agent中表示的是请求客户端的信息,下面自定义user-agent

    @Test
    //header
    public void httpsHeader() {
        //定义的代理配置信息
        RestAssured.proxy = host("127.0.0.1").withPort(8888);//127.0.0.1
        //忽略 tls 证书校验
        RestAssured.useRelaxedHTTPSValidation();
        given()
                .header("User-Agent", "Client-Hui","Client-Dai")//自定义 user-agent请求消息头
                .when()
                .get(url + "/get")
                .then()
                .log().all().statusCode(200);
    }
    @Test
    //headers
    public void httpsHeaders() {
        //定义的代理配置信息
        RestAssured.proxy = host("127.0.0.1").withPort(8888);//127.0.0.1
        //忽略 tls 证书校验
        RestAssured.useRelaxedHTTPSValidation();
        given()
                //.header("User-Agent", "client-hui","client-dai")//自定义 user-agent请求消息头
                .headers("User-Agent","hui","User-Agent2","dai")
                .when()
                .get(url + "/get")
                .then()
                .log().all().statusCode(200);
    }

2.设置cookie

添加请求cookie,有两种方式,一种是添加到header中
另一种是使用given()中的cookie方法,如代码所示:

    @Test
    //使用header添加cookie
    public void AddCookieByHeader() {
        //定义的代理配置信息
        RestAssured.proxy = host("127.0.0.1").withPort(8888);//127.0.0.1
        //忽略 tls 证书校验
        RestAssured.useRelaxedHTTPSValidation();
        given()
                .log().all()
                .headers("Cookie", "cookie-value")
                .when()
                .get(url + "/get")
                .then()
                .log().all().statusCode(200);
    }

    @Test
    //使用cookie添加cookie
    public void AddCookie() {
        //定义的代理配置信息
        RestAssured.proxy = host("127.0.0.1").withPort(8888);//127.0.0.1
        //忽略 tls 证书校验
        RestAssured.useRelaxedHTTPSValidation();
        given()
                //.cookie("Cookie","cookies-value")
                .cookies("cookie1", "cookie1", "cookie2", "cookie2")
                .when()
                .get(url + "/get")
                .then()
                .log().all().statusCode(200);
    }

五、设置超时时间

分为下面的步骤

  • 创建HttpClientConfig实例,并设置超时时间(单位毫秒)
  • 创建RestAssuredConfig实例,将上面设置超时时间的HttpClientConfig注入到RestAssuredConfig中
  • given中调用config,引入RestAssuredConfig
    下面用例中,case2将会超时 case1和case3顺利执行
import io.restassured.RestAssured;
import io.restassured.config.HttpClientConfig;
import io.restassured.config.RestAssuredConfig;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;

/**
 * 设置超时
 */
public class TimeOutTest {
    @BeforeAll
    public static void setupClass() {
        RestAssured.baseURI = "https://httpbin.ceshiren.com";
    }

    @Test
    void case1() {

        given()
                .when()
                .get("/get")
                .then();
    }

    @Test
        //阻塞
    void case2() {
        //设置http客户端请求超时时间 单位毫秒 参数名为 http.socket.timeout
        HttpClientConfig clientConfig = HttpClientConfig.httpClientConfig()
                .setParam("http.socket.timeout", 3000);
        //设置RestAssuredConfig 注入创建的httpConfig
        RestAssuredConfig timeout = RestAssuredConfig.config().httpClient(clientConfig);

        given()
                .config(timeout)//配置前面创建的RestAssured
                .when()
                .get("/delay/10")//该接口延迟10s
                .then();
    }

    @Test
    void case3() {
        given()
                .when()
                .get("/get")
                .then();
    }
}

六、上传文件

使用given()中multiPart()上传文件,multiPart不仅可以用来上传文件,还可以填写key-value形式的参数
multipart可以用来上传多个文件,需要写多个multipart

import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.io.File;

import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;

/**
 * 上传文件学习
 */
public class UploadFileTest {
    @BeforeAll
    static void setupClass(){
        RestAssured.baseURI = "https://httpbin.ceshiren.com";//设置公共域名
        RestAssured.proxy = host("localhost").withPort(8888);//设置代理
        RestAssured.useRelaxedHTTPSValidation();
    }
    @Test
    void uploadFile(){
        File file = new File("D:\\test\\test.txt");//加载文件
        given()
                .multiPart("test file",file)//文件名 文件
                .
                .log().all()
                .when()
                .post("/post")
                .then()
                .log().body()
                .statusCode(200);
    }
}

上面的请求发送后,抓包得到的信息如下
上传文件的header中,content-type:multipart/form-data
在这里插入图片描述

七、操作jdbc

这里操作mysql因此需要引入mysql驱动的依赖

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

想要连接数据库mysql需要知道数据库的访问地址以及用户名密码,一般不同的用户拥有不同的权限,考虑道实际工作场景,操作数据库比较敏感,尤其是业务复杂,表关联复杂时,操作数据库进行增删改容易造成问你题,测试过程一般只能拥有只读权限,下面代码根据访问的地址、用户名、密码 创建数据库连接

url=“jdbc:mysql://访问地址:端口/哪一个数据库”
username=“用户名”
password=“密码”
建一个工具类来创建jdbc连接

public class DatabaseUtils {
    Connection connection = null;
    Statement statement = null;

    public DatabaseUtils(String url, String username, String password) {
        try {
            connection = DriverManager.getConnection(url, username, password);
            statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }
}

1.简单查询

使用代码来进行查询:
下面使用sql查询数据库信息,并获取信息
下面sql根据name查Id,这里查询的结果只返回一个值,代码如下
select id from table where name = 1

public Integer queryIdBySql(String sql) {
        Integer res;
        try {
            ResultSet resultSet = statement.executeQuery(sql);
            resultSet.first();
            res = resultSet.getInt("id");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return res;
    }

2.进阶版查询

上面代码看的出来,查询的参数是id,是一个int型,在日常实际使用中返回的参数什么类型都可能有,因此需要写一个通用的方法
这里采用JsonPath来提取参数的形式实现这个方法,因此需要将数据库查询得到的数据弄成Json
因此用到提取Json的依赖

<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>jooq</artifactId>
    <version>3.11.11</version>
</dependency>
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
    <scope>test</scope>
</dependency>

先查询得到结果集,再将结果集中的数据遍历放入到List中,再将数据转换为Json

public String getResultSetBySQL(String sql_query) {
        // 格式转换将ResultSet 转换为 标准的json格式,方便完成断言。
        try {
            ResultSet resultSet = statement.executeQuery(sql_query);
            // 获取所有
            ResultSetMetaData md = resultSet.getMetaData();
            int numCols = md.getColumnCount();
            // 获取所有的数据表列名
            List<String> colNames = new ArrayList<>();
            for (int i = 1; i <= numCols; i++) {
                String name = md.getColumnName(i);
                colNames.add(name);
            }
            // 返回一个json结构的查询结果
            return DSL.using(connection)
                    .fetch(resultSet)
                    .map(new RecordMapper() {
                        @Override
                        public JSONObject map(Record r) {
                            JSONObject obj = new JSONObject();
                            colNames.forEach(cn -> obj.put(cn, r.get(cn)));
                            return obj;
                        }
                    }).toString();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 如果异常,return 空 json,不影响后续逻辑执行
        return "{}";
    }

八、加解密

1.Base64

base64的加解密使用的是 org.apache.commons.codec.binary.Base64
加密使用Base64.encodeBase64String方法,将一个字节数据加密得到密文字符串
解密是使用Base64.decodeBase64方法,将一串密文字符串,解密成字节数组,解密后需要将字节数组转换成字符串才能得到明文,要注意的是,容易出现乱码,因此要使用标准的编码字符类型,这里用Utf-8

    @Test
    void encryBase64() {
        //加密铭文 hogwarts
        byte[] arr = "test".getBytes(StandardCharsets.UTF_8);
        String encode = Base64.encodeBase64String(arr);
        System.out.println("密文:" + encode);
        //解密
        byte[] res = Base64.decodeBase64(encode);
        String decode = new String(res,StandardCharsets.UTF_8);
        System.out.println("明文:" + decode);

    }

总结

以上是rest_assured框架进行resful接口测试的基本用法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值