DolphinScheduler 如何用 Java+Rest-Assured+PageObject 进行自动化测试
创始人
2024-06-03 08:15:34
0

点击蓝字 关注我们

1a851a17f0cb079d4bdf19ce526f500f.png

作者 | 闫旭平

本文将介绍如何基于 DolphinScheduler 和 REST Assured 来进行接口自动化测试,并使用 PageObject 模式管理你的测试用例。

最终产物:通过 PageObject +REST Assured + Junit 完成你的 Java 接口自动化测试,更加快捷、高效地保证你的项目接口质量。

01

概念简介

01

接口自动化测试

一般讲的接口测试指的是对某个给定接口进行功能测试,输入不同的参数时,接口返回值是否正确。下图是经典的测试金字塔模型。

ef8f42cfd54d90abb51f2a1ce833c20f.png

在这个模型中,越往下比例会占的越高,也就是说在一个产品测试中,单元测试比例是最高的,依次是接口测试和 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 
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

8b16e7fa53972b79f83e326cae0435e9.png

02

REST Assured环境

pom.xml中添加

io.rest-assuredrest-assured5.3.0

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 query= new HashMap();public static RequestSpecification baseRequest = given();public static String template(String pathfile, HashMap 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;@BeforeAllstatic void setUp() {if (project == null){project=new project();}}@AfterAllstatic 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@Disabledvoid 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{@Testvoid 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{@Testvoid 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);}}}

测试结果:

4c57cc4a9ef47d5b0b5c5d986378ec05.png

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 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 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 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;@BeforeEachvoid setUp() {if (datasource == null){datasource=new datasource();}}@AfterEachvoid tearDown() {}@Testvoid create() throws IOException {HashMap 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));}@Testvoid connet() throws IOException {HashMap 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));}
}

测试结果:

21fdc779fa1db1a3f08f7f148a794b5c.png

测试用例源码地址:https://github.com/XuXuClassMate/My_Test_JAProject/tree/master/dolphin/org.xuxuclassmate

05

总结

本文主要介绍了在 Apache DolphinScheduler 使用 Rest-Assured 进行接口自动化测试的过程,我们使用PageObject 来管理测试用例,可以降低测试用例及单个接口的维护成本。

参与贡献

随着国内开源的迅猛崛起,Apache DolphinScheduler 社区迎来蓬勃发展,为了做更好用、易用的调度,真诚欢迎热爱开源的伙伴加入到开源社区中来,为中国开源崛起献上一份自己的力量,让本土开源走向全球。

80fcade3acac9ad7ceb688a07d264527.png

参与 DolphinScheduler 社区有非常多的参与贡献的方式,包括:

ff4e2c78fe8c5bb7d645fd49622c0d81.png

贡献第一个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) ,手把手教会您( 贡献者不分水平高低,有问必答,关键是有一颗愿意贡献的心 )。

33bd56074b9f5e9ae3f44cb6eedd64b9.jpeg

添加社区小助手微信(Leonard-ds) 

添加小助手微信时请说明想参与贡献。

来吧,开源社区非常期待您的参与。

< 🐬🐬 >

更多精彩推荐

☞Apache DolphinScheduler GitHub Star 突破 10000!

☞优秀用户案例有奖征集 | 活动火热开启,快来投稿!

☞BIGO 如何做到夜间同时运行 2.4K 个工作流实例?

☞DolphinScheduler×长安汽车 | 千万级数据接入能力智能网联汽车云平台引进核心调度系统

☞去年办了这么多场Meetup都没有你,2023年赶紧安排起来!

☞Apache DolphinScheduler 3.1.4 版本发布,修复一键安装报错问题

☞迁移工具 Air2phin 宣布开源,2 步迁移 Airflow 至 Dolphinscheduler

我知道你在看4322d67fbf66f09a84e3a5a30cd6d6fd.png

相关内容

热门资讯

安卓系统用的华为应用,探索智能... 你知道吗?在安卓系统里,华为的应用可是个宝库呢!它们不仅功能强大,而且使用起来超级方便。今天,就让我...
安卓变ios系统魅蓝 你知道吗?最近有个朋友突然告诉我,他要把自己的安卓手机换成iOS系统,而且还是魅蓝品牌的!这可真是让...
幻书启世录安卓系统,安卓世界中... 亲爱的读者们,你是否曾在某个夜晚,被一本神奇的书所吸引,仿佛它拥有着穿越时空的力量?今天,我要带你走...
电脑安装安卓系统进不去,安卓系... 电脑安装安卓系统后竟然进不去,这可真是让人头疼的问题啊!你是不是也遇到了这种情况,心里直呼“怎么办怎...
用键盘切换控制安卓系统,畅享安... 你有没有想过,用键盘来控制你的安卓手机?是的,你没听错,就是那个我们每天敲敲打打的小玩意儿——键盘。...
小米安卓镜像系统在哪,小米安卓... 你有没有想过,你的小米手机里有一个隐藏的宝藏——安卓镜像系统?没错,就是那个可以让你的手机瞬间变身成...
安卓手机下载排班系统,高效排班... 你有没有想过,每天忙碌的工作中,有没有什么好帮手能帮你轻松管理时间呢?今天,就让我来给你介绍一个超级...
桌面组件如何弄安卓系统,桌面组... 亲爱的桌面爱好者们,你是否曾梦想过将安卓系统搬到你的电脑桌面上?想象那些流畅的动画、丰富的应用,还有...
安卓13系统介绍视频,新功能与... 亲爱的读者们,你是否对安卓13系统充满好奇?想要一探究竟,却又苦于没有足够的时间去研究?别担心,今天...
车机安卓7.1系统,功能升级与... 你有没有发现,现在的车机系统越来越智能了?尤其是那些搭载了安卓7.1系统的车机,简直就像是个贴心的智...
安卓系统下如何读pdf,And... 你有没有遇到过这种情况:手机里存了一大堆PDF文件,可是怎么也找不到一个能顺畅阅读的工具?别急,今天...
安卓系统全国通用的吗,畅享智能... 你有没有想过,为什么你的手机里装的是安卓系统呢?安卓系统,这个名字听起来是不是有点神秘?今天,就让我...
假苹果手机8安卓系统,颠覆传统... 你有没有想过,如果苹果手机突然变成了安卓系统,会是怎样的景象呢?想象那熟悉的苹果外观,却运行着安卓的...
安卓12.0系统vivo有吗,... 你有没有听说最近安卓系统又升级啦?没错,就是那个让手机焕然一新的安卓12.0系统!那么,咱们国内的手...
核心芯片和安卓系统,探索核心芯... 你知道吗?在科技的世界里,有一对“黄金搭档”正悄悄改变着我们的生活。他们就是——核心芯片和安卓系统。...
如何调安卓系统屏幕颜色,安卓系... 亲爱的手机控们,你是否曾觉得安卓系统的屏幕颜色不够个性,或者是因为长时间盯着屏幕而感到眼睛疲劳?别担...
旧台式电脑安装安卓系统,轻松安... 你那台旧台式电脑是不是已经服役多年,性能逐渐力不从心,却又不忍心让它退役呢?别急,今天就来教你怎么给...
美国要求关闭安卓系统,科技霸权... 美国要求关闭安卓系统:一场技术革新还是政治博弈?在数字化时代,智能手机已经成为我们生活中不可或缺的一...
安卓系统日记本 你有没有发现,手机里的安卓系统日记本,简直就是记录生活点滴的宝藏库呢?想象每天忙碌的生活中,有没有那...
安卓手机广告最少的系统,探索安... 你有没有发现,用安卓手机的时候,广告总是无处不在,让人烦得要命?不过别急,今天我要给你揭秘一个秘密—...