当前位置:   article > 正文

DolphinScheduler 如何用 Java+Rest-Assured+PageObject 进行自动化测试_dolphinscheduler java

dolphinscheduler java

作者 | XuXuClassMate

摘要

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

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

概念简介

接口自动化测试

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

在这个模型中,越往下比例会占的越高,也就是说在一个产品测试中,单元测试比例是最高的,依次是接口测试和 UI自动化测试,最顶端是人工测试部分。服务端接口测试在中部,承上启下,由此可见其重要性。

简单来说,接口测试就是参照接口文档,调用接口,看结果的返回是否跟文档说明一致;另外,再测试一下接口对异常逻辑的处理比如非法参数或边界值。

而接口自动化测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。接口自动化测试具有数据与脚本分离,测试结果自动提交通知,提高测试脚本和测试数据的维护便利等优点。

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 进行接口自动化测试的全过程。

安装

Java8环境

sudo apt-get update
sudo apt-get install openjdk-8-jdk
java -version
  • 1
  • 2
  • 3

配置Java环境变量,~/.bashrc 或者 ~/.zshrc

# 确认你的jdk的目录是否为这个,配置环境变量
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64
export PATH=$PATH:$JAVA_HOME/bin
  • 1
  • 2
  • 3

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

启动DolphinScheduler

## start DolphinScheduler
cd apache-dolphinscheduler-3.1.2-bin
bash bin/dolphinscheduler-daemon.sh start standalone-server

## 可以通过以下命令查看日志
# tail -500f standalone-server/logs/dolphinscheduler-standalone.log
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

启动后,稍等一会服务启动即可进入DolphinScheduler的页面

打开 http://localhost:12345/dolphinscheduler/ui,可以看到DolphinScheduler页面

账号:admin,密码:dolphinscheduler123

REST Assured环境

pom.xml中添加

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>5.3.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

新建配置文件

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

实例化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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

初始化接口,重复的参数提炼成新方法供后面继承的方法调用

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

对项目增删改查接口进行建模

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

对项目增删改查接口进行测试

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);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

测试结果:

对数据源中心接口进行建模

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

数据源中心接口测试用例:

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));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

测试结果:

测试用例源码地址:https://github.com/XuXuClassMate/My_Test_JAProject/tree/master/dolphinscheduler-test-case

总结

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/826717
推荐阅读
相关标签
  

闽ICP备14008679号