赞
踩
点击蓝字 关注我们
作者 | 闫旭平
本文将介绍如何基于 DolphinScheduler 和 REST Assured 来进行接口自动化测试,并使用 PageObject 模式管理你的测试用例。
最终产物:通过 PageObject +REST Assured + Junit 完成你的 Java 接口自动化测试,更加快捷、高效地保证你的项目接口质量。
✦
✦
01
概念简介
01
接口自动化测试
一般讲的接口测试指的是对某个给定接口进行功能测试,输入不同的参数时,接口返回值是否正确。下图是经典的测试金字塔模型。
在这个模型中,越往下比例会占的越高,也就是说在一个产品测试中,单元测试比例是最高的,依次是接口测试和 UI自动化测试,最顶端是人工测试部分。服务端接口测试在中部,承上启下,由此可见其重要性。
简单来说,接口测试就是参照接口文档,调用接口,看结果的返回是否跟文档说明一致;另外,再测试一下接口对异常逻辑的处理比如非法参数或边界值。
而接口自动化测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。接口自动化测试具有数据与脚本分离,测试结果自动提交通知,提高测试脚本和测试数据的维护便利等优点。
02
REST-assured
REST-assured 是一个开源的 Java 库,用来测试和验证 REST API。动态语言如 Groovy,Ruby 执行 API 测试非常简单,但对 Java 来说就有点费力了。而 REST Assured 使得用 Java 语言测试 API 和使用 Ruby 和 Groovy 执行测试一样简单。
REST Assured 是一种 JAVA DSL(Domain Specific Language)领域特定语言 [ 通常被定义为一种特别针对某类特殊问题的计算机语言,它不打算解决其领域外的问题。],用来简化测试 REST Services,并简化 HTTP Builder 顶层。REST Assured 支持发起任意 HTTP 请求 GET, POST, PUT, DELETE, OPTIONS, PATCH 和 HEAD, 包括详述清单,比如参数,头部,cookie 和实体,并验证这些请求的响应。
REST Assured 基于Apache Http Client,提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且支持 HTTP 协议最新的版本。
下面介绍基于 DolphinScheduler 和 REST Assured 进行接口自动化测试的全过程。
02
安装
01
Java8环境
- sudo apt-get update
- sudo apt-get install openjdk-8-jdk
- java -version
配置Java环境变量,~/.bashrc 或者 ~/.zshrc
- # 确认你的jdk的目录是否为这个,配置环境变量
- export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64
- export PATH=$PATH:$JAVA_HOME/bin
Apache DolphinScheduler 3.1.2
详细安装可见官网:https://dolphinscheduler.apache.org/en-us/docs/latest/user_doc/guide/installation/standalone.html
下载DolphinScheduler 3.1.2
- # 进入需要安装DolphinScheduler的目录
- mkdir dolphinscheduler && cd "$_"
- ## install DolphinScheduler
- wget <https://mirrors.tuna.tsinghua.edu.cn/apache/dolphinscheduler/3.1.2/apache-dolphinscheduler-3.1.2-bin.tar.gz>
- tar -zxvf apache-dolphinscheduler-3.1.2-bin.tar.gz
- rm apache-dolphinscheduler-3.1.2-bin.tar.gz
启动DolphinScheduler
- ## start DolphinScheduler
- cd apache-dolphinscheduler-3.1.2-bin
- bash bin/dolphinscheduler-daemon.sh start standalone-server
-
-
- ## 可以通过以下命令查看日志
启动后,稍等一会服务启动即可进入DolphinScheduler的页面
打开 http://localhost:12345/dolphinscheduler/ui,可以看到DolphinScheduler页面
账号:admin,密码:dolphinscheduler123
02
REST Assured环境
pom.xml中添加
- <dependency>
- <groupId>io.rest-assured</groupId>
- <artifactId>rest-assured</artifactId>
- <version>5.3.0</version>
- </dependency>
03
新建配置文件
- public class dolphinConfig {
- public String userName= "admin";
- public String passWord = "dolphinscheduler123";
- public String baseUrl = "http://localhost:12345/dolphinscheduler";
-
-
- private static dolphinConfig dolphinConfig;
- public static dolphinConfig getInstance(){
- if (dolphinConfig==null){
- dolphinConfig=new dolphinConfig();
- }
- return dolphinConfig;
- }
- }
实例化RequestSpecification方法减少重复代码
Template方法是修改json文件,进行json文件参数化测试,只针对差异化参数修改json文件
- import com.jayway.jsonpath.DocumentContext;
- import com.jayway.jsonpath.JsonPath;
- import io.restassured.specification.RequestSpecification;
- import java.io.IOException;
- import java.nio.charset.StandardCharsets;
- import java.nio.file.Files;
- import java.nio.file.Path;
- import java.nio.file.Paths;
- import java.util.HashMap;
- import static io.restassured.RestAssured.given;
-
-
- public class Restful {
- HashMap<String, Object> query= new HashMap<String, Object>();
- public static RequestSpecification baseRequest = given();
-
-
- public static String template(String pathfile, HashMap<String, Object> map) throws IOException {
- Path path = Paths.get(pathfile);
- String jsonString = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
- DocumentContext document = JsonPath.parse(jsonString);
- map.entrySet().forEach(entry->{
- document.set(entry.getKey(),entry.getValue());
- });
- return document.jsonString();
- }
- }

初始化接口,重复的参数提炼成新方法供后面继承的方法调用
- import static io.restassured.RestAssured.given;
-
-
- public class baseRequest extends Restful{
- public baseRequest() {
- api_init();
- }
- public void api_init(){
- baseRequest = given()
- .log().all()
- .header("sessionId", dolphin.session())
- .header("Accept","application/json, text/plain, */*")
- .header("language","zh_CN")
- .header("Content-Type","application/x-www-form-urlencoded")
- //.contentType(ContentType.JSON);
- }
- }

Session持久化,减少冗余鉴权
- import static org.hamcrest.Matchers.equalTo;
-
-
- public class dolphin extends baseRequest {
- public static String baseUrl = null;
- public static String userName = null;
- public static String passWord = null;
- private static String sessionId = null;
- public static String logIn(){
- baseUrl = dolphinConfig.getInstance().baseUrl;
- userName = dolphinConfig.getInstance().userName;
- passWord = dolphinConfig.getInstance().passWord;
- sessionId = baseRequest
- .queryParam("userName",userName)
- .queryParam("userPassword",passWord)
- .post(baseUrl+"/login")
- .then().statusCode(200)
- .body("code", equalTo(0)).extract().path("data.sessionId");
- return sessionId;
- }
- public static String session(){
- if (sessionId== null){
- sessionId= logIn();
- }
- return sessionId;
- }
- }

对项目增删改查接口进行建模
- import base.dolphin;
- import io.restassured.response.Response;
-
-
- public class project extends dolphin {
- public Response create(String projectName,String description){
- Response response= baseRequest
- .param("projectName",projectName)
- .param("description",description)
- .param("userName",userName)
- .when().post(baseUrl+"/projects")
- .then().statusCode(201).extract().response();
- api_init();
- return response;
- }
-
-
- public Response update(Long projectCode,String projectName,String description){
- Response response= baseRequest
- .param("projectName",projectName).param("description",description)
- .param("userName",userName)
- .when().put(baseUrl+"/projects/"+ projectCode)
- .then().statusCode(200).extract().response();
- api_init();
- return response;
- }
-
-
- public Response delete(Long projectCode){
- Response response= baseRequest
- .when().delete(baseUrl+"/projects/"+ projectCode)
- .then().statusCode(200).extract().response();
- api_init();
- return response;
- }
-
-
- public Response search(Integer pageSize, Integer pageNo, String searchName){
- if (pageSize ==null | pageSize < 10){
- pageSize =10;
- }
- if (pageNo ==null | pageNo < 1) {
- pageNo =1;
- }
- Response response= baseRequest
- .param("pageSize",pageSize)
- .param("pageNo",pageNo)
- .param("searchVal",searchName)
- .when().get(baseUrl+"/projects")
- .then().statusCode(200).extract().response();
- api_init();
- return response;
- }
- public Response search(String searchName){
- Response response= baseRequest
- .param("pageSize",10)
- .param("pageNo",1)
- .param("searchVal",searchName)
- .when().get(baseUrl+"/projects")
- .then().statusCode(200).extract().response();
- api_init();
- return response;
- }
- }

对项目增删改查接口进行测试
- import org.junit.jupiter.api.*;
- import org.junit.jupiter.params.ParameterizedTest;
- import org.junit.jupiter.params.provider.ValueSource;
- import static org.hamcrest.Matchers.equalTo;
-
-
- class projectTest {
- static project project;
-
-
- @BeforeAll
- static void setUp() {
- if (project == null){
- project=new project();
- }
- }
-
-
- @AfterAll
- static void setDown(){
- int total = project.search("").then().log().all().extract().path("data.total");
- for (int i = 0; i < total; i++) {
- Long projectCode = project.search("").then().extract().path("data.totalList[0].code");
- project.delete(projectCode);
- }
- }
- @Test
- @Disabled
- void search(){
- project.search("").body();
- String code=String.valueOf(project.search("").path("data.totalList[0].find{ it.name == 'test666' }.code"));
- System.out.println("projectcode"+ code);
- }
- @ParameterizedTest
- @ValueSource(strings={"ApiTestCreateProject123","ApiTestCreateProject456","ApiTestCreateProject789"})
- @DisplayName("create project Testcase")
- void create(String name) {
- String projectname =name;
- project.create(projectname,"")
- .then().body("code", equalTo(0));
- project.search(projectname)
- .then().body("data.totalList[0].name",equalTo(projectname));
- }
- @Nested
- @DisplayName("update projectName Testcase")
- class update_delete{
- @Test
- void update() {
- project.create("ApiTestCreateProject_update_init","ApiTestCreateProject_update_init")
- .then().body("code", equalTo(0));
- Long projectCode = project.search("ApiTestCreateProject_update_init")
- .then().log().all().body("data.totalList[0].name", equalTo("ApiTestCreateProject_update_init"))
- .extract().path("data.totalList[0].code");
- project.update(projectCode,"ApiTestCreateProject_update_now","ApiTestCreateProject_update_now")
- .then().body("code", equalTo(0));
- project.search("ApiTestCreateProject_update_now")
- .then().body("data.totalList[0].name",equalTo("ApiTestCreateProject_update_now"));
- }
- @Nested
- @DisplayName("delete project")
- class delete{
- @Test
- void delete(){
- Long projectCode = project.search("ApiTestCreateProject_update_now")
- .then().log().all().body("data.totalList[0].name", equalTo("ApiTestCreateProject_update_now"))
- .extract().path("data.totalList[0].code");
- project.delete(projectCode);
- }
- }
- }

测试结果:
04
对数据源中心接口进行建模
- import base.dolphin;
- import io.restassured.response.Response;
- import java.io.IOException;
- import java.util.HashMap;
-
-
- public class datasource extends dolphin {
- public Response create(HashMap<String,Object> map) throws IOException {
- String body = template("dolphin/resource/data/database.json",map);
- Response response = baseRequest.body(body)
- .when().post(baseUrl+"/datasources")
- .then().statusCode(201).extract().response();
- api_init();
- return response;
- }
- public Response connect(HashMap<String, Object> map) throws IOException {
- String body = template("dolphin/resource/data/database.json",map);
- Response response = baseRequest.body(body)
- .when().post(baseUrl+"/datasources/connect")
- .then().statusCode(200).extract().response();
- api_init();
- return response;
- }
- public Response update(int datasourceid,HashMap<String, Object> map) throws IOException {
- String body = template("/data/database.json",map);
- Response response = baseRequest.body(body)
- .when().put(baseUrl+"/datasources/"+ datasourceid)
- .then().statusCode(200).extract().response();
- api_init();
- return response;
- }
- }

数据源中心接口测试用例:
- import org.junit.jupiter.api.AfterEach;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import java.io.IOException;
- import java.util.HashMap;
- import static org.hamcrest.Matchers.equalTo;
-
-
- class datasourceTest {
- datasource datasource;
-
-
- @BeforeEach
- void setUp() {
- if (datasource == null){
- datasource=new datasource();
- }
- }
-
-
- @AfterEach
- void tearDown() {
- }
-
-
- @Test
- void create() throws IOException {
- HashMap<String,Object> map=new HashMap<>();
- map.put("type","MYSQL");
- map.put("name","apiTestmysql");
- map.put("userName","root");
- map.put("password","root@123");
- datasource.create(map).then().body("code",equalTo(0));
- }
- @Test
- void connet() throws IOException {
- HashMap<String, Object> map=new HashMap<>();
- map.put("type","MYSQL");
- map.put("name","apiTestmysql");
- map.put("userName","root");
- map.put("password","root@123");
- map.put("database","xuxutestdb123");
- datasource.connect(map).then().body("code",equalTo(0));
- }
- }

测试结果:
测试用例源码地址:https://github.com/XuXuClassMate/My_Test_JAProject/tree/master/dolphin/org.xuxuclassmate
05
总结
本文主要介绍了在 Apache DolphinScheduler 使用 Rest-Assured 进行接口自动化测试的过程,我们使用PageObject 来管理测试用例,可以降低测试用例及单个接口的维护成本。
参与贡献
随着国内开源的迅猛崛起,Apache DolphinScheduler 社区迎来蓬勃发展,为了做更好用、易用的调度,真诚欢迎热爱开源的伙伴加入到开源社区中来,为中国开源崛起献上一份自己的力量,让本土开源走向全球。
参与 DolphinScheduler 社区有非常多的参与贡献的方式,包括:
贡献第一个PR(文档、代码) 我们也希望是简单的,第一个PR用于熟悉提交的流程和社区协作以及感受社区的友好度。
社区汇总了以下适合新手的问题列表:https://github.com/apache/dolphinscheduler/issues/5689
非新手问题列表:https://github.com/apache/dolphinscheduler/issues?q=is%3Aopen+is%3Aissue+label%3A%22volunteer+wanted%22
如何参与贡献链接:https://dolphinscheduler.apache.org/zh-cn/community/development/contribute.html
来吧,DolphinScheduler开源社区需要您的参与,为中国开源崛起添砖加瓦吧,哪怕只是小小的一块瓦,汇聚起来的力量也是巨大的。
参与开源可以近距离与各路高手切磋,迅速提升自己的技能,如果您想参与贡献,我们有个贡献者种子孵化群,可以添加社区小助手微信(Leonard-ds) ,手把手教会您( 贡献者不分水平高低,有问必答,关键是有一颗愿意贡献的心 )。
添加社区小助手微信(Leonard-ds)
添加小助手微信时请说明想参与贡献。
来吧,开源社区非常期待您的参与。
< 声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。