【自动化测试实战】从 0 到 1 搭建 Dubbo 接口自动化测试

news2024/11/16 19:31:01

前言

1、Dubbo 接口自动化测试框架实现逻辑

2、框架具体功能

3、关键实践

3.1 下载 provider 的 jar 包,并代理声明 +zookeeper 设置

3.2 邮件发送功能

3.3 封装 Dubbo 接口信息类

3.4 利用 JMeter 调用 provider 服务,并断言,邮件报警

3.5 利用 Testng 注释,调用 Dubbo 接口类,进行测试

4、利用 Jenkins 自动化运行 Dubbo 测试项目

软件测试面试小程序


前言

由于公司 Dubbo 接口数量较多,且核心接口较多,故需要一套 Dubbo 接口自动化框架,来提高测试效率。

1、Dubbo 接口自动化测试框架实现逻辑

2、框架具体功能

框架需要
实现功能

功能说明当前版本是否已实现从 maven 库自动下载所需 jar 包为了更好的自动化,所有的 provider 的 jar 都从 maven 下载,避免手工导入已实现参数自定义匹配不同的 Dubbo 接口,不同的参数需求已实现断言功能一个接口是否调用成功,在于断言是否成功已实现邮件报警功能如果 Dubbo 接口调用 provider 失败,自动进行邮件报警已实现自动运行利用 jenkins 自动运行已实现

3、关键实践

由于目前阶段刚接触 java 及 Dubbo,本次实现为基本功能实现,数据隔离等没有做。

3.1 下载 provider 的 jar 包,并代理声明 +zookeeper 设置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:Dubbo="http://code.alibabatech.com/schema/Dubbo"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/Dubbo
       http://code.alibabatech.com/schema/Dubbo/Dubbo.xsd">

    <Dubbo:application name="demo-consumer"/>

    <Dubbo:registry address="zookeeper://1127.0.0.1:2181" />

    <Dubbo:reference id="IPromiseForOrderService" interface="com.test.api.IPromiseForOrderService" version="1.0" check="true"/>
</beans>

3.2 邮件发送功能

(1)邮件服务器配置在 mailConfig.properties


(2)获取 mailconfig 信息,并封装成类

public class MailConfig {
    private static final String PROPERTIES_DEFAULT = "mailConfig.properties";
    public static String host;
    public static Integer port;
    public static String userName;
    public static String passWord;
    public static String emailForm;
    public static String timeout;
    public static String personal;
    public static Properties properties;
    static{
        init();
    }

    /**
     * 初始化
     */
    private static void init() {
        properties = new Properties();
        InputStream inputStream = null;
        try{

            inputStream = MailConfig.class.getClassLoader().getResourceAsStream(PROPERTIES_DEFAULT);
            properties.load(inputStream);
            inputStream.close();
            host = properties.getProperty("mailHost");
            port = Integer.parseInt(properties.getProperty("mailPort"));
            userName = properties.getProperty("mailUsername");
            passWord = properties.getProperty("mailPassword");
            emailForm = properties.getProperty("mailFrom");
            timeout = properties.getProperty("mailTimeout");
            personal = " 自动化测试 ";
        } catch(IOException e){
            e.printStackTrace();
        }
    }
}

(3)封装发送邮件功能

public class MailUtil {
    private static final String HOST = MailConfig.host;
    private static final Integer PORT = MailConfig.port;
    private static final String USERNAME = MailConfig.userName;
    private static final String PASSWORD = MailConfig.passWord;
    private static final String emailForm = MailConfig.emailForm;
    private static final String timeout = MailConfig.timeout;
    private static final String personal = MailConfig.personal;
    private static JavaMailSenderImpl mailSender = createMailSender();
    /**
     * 邮件发送器
     *
     * @return 配置好的工具
     */
    private static JavaMailSenderImpl createMailSender() {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost(HOST);
        sender.setPort(PORT);
        sender.setUsername(USERNAME);
        sender.setPassword(PASSWORD);
        sender.setDefaultEncoding("Utf-8");
        Properties p = new Properties();
        p.setProperty("mail.smtp.timeout", timeout);
        p.setProperty("mail.smtp.auth", "false");
        sender.setJavaMailProperties(p);
        return sender;
    }

    /**
     * 发送邮件
     *
     * @param to 接受人
     * @param subject 主题
     * @param html 发送内容
     * @throws MessagingException 异常
     * @throws UnsupportedEncodingException 异常
     */
    public void sendMail(InternetAddress[] to, String subject, String html) throws MessagingException,UnsupportedEncodingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        // 设置 utf-8 或 GBK 编码,否则邮件会有乱码
        MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
        messageHelper.setFrom(emailForm, personal);
        messageHelper.setTo(to);
        messageHelper.setSubject(subject);
        messageHelper.setText(html, false);
        mailSender.send(mimeMessage);
    }
}

3.3 封装 Dubbo 接口信息类

把 Dubbo 接口封装成一个类,方便信息 get 和 set

public class DubboInterfaceInfo {
    private String DubboInterfaceWiki;
    private String DubboInterfacePacketName;
    private String DubboInterfaceClassName;
    private RestRequest request;
    private String responseStatusSuccessful;
    private String responseMessageSuccessful;
    private String DubboInterfaceId;

    public DubboInterfaceInfo() {}

    public String getDubboInterfaceWiki() {
        return this.DubboInterfaceWiki;
    }
    public void setDubboInterfaceWiki(String DubboInterfaceWiki) {
        this.DubboInterfaceWiki = DubboInterfaceWiki;
    }

    public String getDubboInterfacePacketName() {
        return this.DubboInterfacePacketName;
    }
    public void setDubboInterfacePacketName(String DubboInterfacePacketName) {
        this.DubboInterfacePacketName = DubboInterfacePacketName;
    }

    public String getDubboInterfaceClassName() {
        return this.DubboInterfaceClassName;
    }
    public void setDubboInterfaceClassName(String DubboInterfaceClassName) {
        this.DubboInterfaceClassName = DubboInterfaceClassName;
    }

    public RestRequest getRestRequest() {
        return this.request;
    }
    public void setRestRequest(RestRequest request) {
        this.request = request;
    }

    public String getResponseStatusSuccessful() {
        return this.responseStatusSuccessful;
    }
    public void setResponseStatusSuccessful(String responseStatusSuccessful) {
        this.responseStatusSuccessful = responseStatusSuccessful;
    }

    public String getResponseMessageSuccessful() {
        return this.responseMessageSuccessful;
    }
    public void setResponseMessageSuccessful(String responseMessageSuccessful) {
        this.responseMessageSuccessful = responseMessageSuccessful;
    }

    public String getDubboInterfaceId() {
        return this.DubboInterfaceId;
    }
    public void setDubboInterfaceId(String DubboInterfaceId) {
        this.DubboInterfaceId = DubboInterfaceId;
    }
}

3.4 利用 JMeter 调用 provider 服务,并断言,邮件报警

利用 Jmeter 调用 provider 服务,并断言,邮件报警,这些功能封装成 Dubbo 接口测试类,代码如下:

public class IPromiseForOrderServiceTest extends AbstractJavaSamplerClient {
    /**
     * CONTEXT
     * 读取 Dubbo-config.xml 中的内容
     */
    private static final ApplicationContext CONTEXT = new ClassPathXmlApplicationContext("Dubbo-config.xml");
    public DubboInterfaceInfo DubboInterfaceInfo = new DubboInterfaceInfo();
    public String responseSuccess;
    public String responseFail;
    public FreeStockForOrderParam request;
    /**
     * IPromiseForOrderService
     * 此处需要实例化 Dubbo 接口 IPromiseForOrderService,像定义变量一样实例化
     */
    private static IPromiseForOrderService IPromiseForOrderService;

    /**
     * IPromiseForOrderService
     * 以下方法用于 输入 Dubbo 接口信息
     */
    public void DubboInterfaceInfoInitialization () {
        DubboInterfaceInfo.setDubboInterfaceWiki("......");
        DubboInterfaceInfo.setDubboInterfacePacketName("......");
        DubboInterfaceInfo.setDubboInterfaceClassName("......");
        DubboInterfaceInfo.setDubboInterfaceId("......");
        DubboInterfaceInfo.setResponseStatusSuccessful("0");
        DubboInterfaceInfo.setResponseMessageSuccessful("success");
        String orderNo = "orderNo";
        String operater="";
        String channel="";
        String operateId="operateId";
        String version= PromiseVersion.V_1_0_0.getVersion();
        request = new FreeStockForOrderParam();
        if (orderNo != null || orderNo.length() > 0) {
            request.setOrderNo(orderNo);
        }
        if (operater != null || operater.length() > 0) {
            request.setOperater(operater);
        }
        if (channel != null || channel.length() > 0) {
            request.setChannel(channel);
        }
        if (operateId != null || operateId.length() > 0) {
            request.setOperateId(operateId);
        }
        if (version != null || version.length() > 0) {
            request.setVersion(version);
        }
        RestRequest<FreeStockForOrderParam> req = new RestRequest<FreeStockForOrderParam>();
        req.setRequest(request);
        DubboInterfaceInfo.setRestRequest(req);
    }


    @Override
    public void setupTest(JavaSamplerContext arg0){
        IPromiseForOrderService=(IPromiseForOrderService)CONTEXT.getBean("......");
    }

    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
        SampleResult sr = new SampleResult();

        try {
            sr.sampleStart();
            RestResponse responseData = IPromiseForOrderService.freeSaleStock(DubboInterfaceInfo.getRestRequest());
// 自定义 Dubbo 调用成功和失败的邮件正文内容
            responseSuccess =
                             "Dubbo 接口: "
                                     + DubboInterfaceInfo.getDubboInterfaceId() + " 请求成功\r\n"
                                     + "WIKI 地址: " + DubboInterfaceInfo.getDubboInterfaceWiki() + "\r\n"
                                     + "PacketName: " + DubboInterfaceInfo.getDubboInterfacePacketName() + "\r\n"
                                     + "ClassName: " + DubboInterfaceInfo.getDubboInterfaceClassName() + "\r\n"
                                    ;
            responseFail =
                    "Dubbo 接口: " + DubboInterfaceInfo.getDubboInterfaceId() + " 请求失败\r\n"
                            + "WIKI 地址: " + DubboInterfaceInfo.getDubboInterfaceWiki() + "\r\n"
                            + "PacketName: " + DubboInterfaceInfo.getDubboInterfacePacketName() + "\r\n"
                            + "ClassName" + DubboInterfaceInfo.getDubboInterfaceClassName() + "\r\n"
                            + " 请求参数为:Channel: " + request.getChannel() +
                                            " / operater: " + request.getOperater() +
                                            " / OperateId: " + request.getOperateId() +
                                            " / OrderNo: " + request.getOrderNo() +
                                            " / Version: " + request.getVersion()
                            + "\r\n"
                            + " 返回结果为:"
                            + "ResponseStatus: " + responseData.getStatus()
                            + " / ResponseMessage: " + responseData.getMessage()
                            + " / ResponseResult: " + responseData.getResult();


            /**
             * 邮件定义及发送
             */
            InternetAddress[] address = new InternetAddress[2];
            try {
                address[0] = new InternetAddress("lalllalala@qq.com");
                address[1] = new InternetAddress("3456789@qq.com");
            } catch (AddressException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            MailUtil mailUtil = new MailUtil();

            if ((DubboInterfaceInfo.getResponseStatusSuccessful().equals(responseData.getStatus())) && (DubboInterfaceInfo.getResponseMessageSuccessful().equals(responseData.getMessage()))) {
                sr.setSuccessful(true);
                sr.setResponseData("responseData: " + responseData, "utf-8");
                System.out.println(responseSuccess);
                mailUtil.sendMail(address,"Dubbo 接口:" + DubboInterfaceInfo.getDubboInterfaceId() + " 请求成功 ",responseSuccess.toString());

            } else {
                sr.setSuccessful(false);
                System.out.println(responseFail);
                mailUtil.sendMail(address,"Dubbo 接口:" + DubboInterfaceInfo.getDubboInterfaceId() + " 请求失败 ",responseFail.toString());
            }

            sr.sampleEnd();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return sr;
    }


}

3.5 利用 Testng 注释,调用 Dubbo 接口类,进行测试

public class TestngTest {
    @Test()
    public void testDubboInterface() {
        JavaSamplerContext arg0 = new JavaSamplerContext(new Arguments());

        Dubbo 接口测试类 TestForIPromiseForOrderService = new Dubbo 接口测试类 ();
        TestForIPromiseForOrderService.DubboInterfaceInfoInitialization();
        TestForIPromiseForOrderService.setupTest(arg0);
        SampleResult sr = TestForIPromiseForOrderService.runTest(arg0);
    }
}

4、利用 Jenkins 自动化运行 Dubbo 测试项目

至此,大功告成,你可以完成 Dubbo 接口自动化测试了。另,接下来可以加入关联、测试数据分离等功能,让框架变得更加易用。

最后: 为了回馈铁杆粉丝们,我给大家整理了完整的软件测试视频学习教程,朋友们如果需要可以自行免费领取 【保证100%免费】

加入我的软件测试交流群:110685036免费获取~(同行大佬一起学术交流,每晚都有大佬直播分享技术知识点)

软件测试面试小程序

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!

涵盖以下这些面试题板块:

1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux

6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

获取方式 :

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605152.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

音视频基础及海思sample_venc解读

1、sample的整体架构 (1)sample其实是很多个例程&#xff0c;所以有很多个main (2)每一个例程面向一个典型应用&#xff0c;common是通用性主体函数&#xff0c;我们只分析venc (3)基本的架构是&#xff1a;venc中的main调用venc中的功能函数&#xff0c;再调用common中的功…

python基于DeeplabV3Plus开发构建裂缝分割识别系统,并实现裂缝宽度计算测量

在我之前的文章中已经有不少基于裂缝场景的数据开发构建的模型了&#xff0c;感兴趣的话可以自行移步阅读&#xff0c;如下&#xff1a; 《基于yolov5sbifpn实践隧道裂缝裂痕检测》 《基于YOLOV7的桥梁基建裂缝检测》 《水泥路面、桥梁基建、隧道裂痕裂缝检测数据集》 《基…

SpringBoot异步执行方法

1. 源码跟踪 1.简单描述 在SpringBoot2.0.9之前需要手动自定义线程池(如下2.1), 然后指定线程池的名称 SpringBoot2.0.9以及之前的版本,使用的线程池默认是SimpleAsyncTaskExcutor, , 之后的版本使用的是ThreadpoolTaskExecutor 并且不需要手动的创建当前线程池(但往往我们…

多线程基础(五)ThreadLocal与四种引用

一、ThreadLocal ThreadLocal&#xff1a;解决每个线程绑定自己的值&#xff0c;存放线程的私有数据。 public class ThreadLocalTest {public static ThreadLocal local new ThreadLocal();public static void main(String[] args) {if(local.get() null){local.set("…

加成序列 dfs 迭代加深 java

&#x1f351; 加成序列 满足如下条件的序列 X X X&#xff08;序列中元素被标号为 1 、 2 、 3 … m 1、2、3…m 1、2、3…m&#xff09;被称为“加成序列”&#xff1a; KaTeX parse error: Undefined control sequence: \[ at position 2: X\̲[̲1\]1KaTeX parse error…

一文读懂MVCC:数据库中的并发读写利器!

大家好&#xff0c;我是你们的小米&#xff0c;一个积极活泼、喜好分享技术的小伙伴。今天&#xff0c;我想和大家聊一聊数据库领域的一个重要话题——MVCC多版本并发控制。MVCC是MySQL和其他一些数据库系统中常用的并发控制技术&#xff0c;通过它&#xff0c;我们可以在高并发…

如何用 Python 实现所有算法?

学会了 Python 基础知识&#xff0c;想进阶一下&#xff0c;那就来点算法吧&#xff01;毕竟编程语言只是工具&#xff0c;结构算法才是灵魂。 新手如何入门 Python 算法&#xff1f; 几位印度小哥在 GitHub 上建了一个各种 Python 算法的新手入门大全。从原理到代码&#xff0…

milkV-duo的Linux的开发环境搭建

目录 写在前面 内核编译 烧录失败的示例&#xff08;这种情况下就和插上空卡一样) 进入系统 串口进入 SSH接入 写在前面 基本上大部分的问题都能在开源社区上得到答案,记录下我遇到的问题. 附上开源社区 MilkV Community 这里的引脚图和板子的丝印有点对不上&#xff…

竞赛中常用的Python 标准库

对竞赛中常用得标准库进行解析和给出代码模板 目录 1.functools 1.1 cmp_to_key 1.2 lru_cache&#xff08;记忆化存储&#xff0c;加快递归速度&#xff09; 2.collections 2.1 deque 2.1.1 单调对列实现 2.1.2 BFS广搜 3.sys 3.1 sys.maxsize 3.2 sys.exit() 3.…

使用python的plot绘制loss、acc曲线,并存储成图片

使用 python的plot 绘制网络训练过程中的的 loss 曲线以及准确率变化曲线&#xff0c;这里的主要思想就时先把想要的损失值以及准确率值保存下来&#xff0c;保存到 .txt 文件中&#xff0c;待网络训练结束&#xff0c;我们再拿这存储的数据绘制各种曲线。 其大致步骤为&#x…

代码自动生成工具——TableGo(实例演示)

一、常用的代码生成器工具介绍 在SpringBoot项目开发中&#xff0c;为了提高开发效率&#xff0c;我们经常需要使用代码自动生成工具来生成一些重复性的代码&#xff0c;比如实体类、DAO、Service、Controller等等。下面介绍几个常用的代码自动生成工具&#xff1a; ①、MyBat…

如何在Linux 启用组播

第一章: 前言 多播技术&#xff0c;也被称为“组播”&#xff0c;是一种网络通信机制&#xff0c;它允许一个节点&#xff08;发送者&#xff09;向一组特定的节点&#xff08;接收者&#xff09;发送信息。这种方式在网络编程中非常有用&#xff0c;因为它可以大大提高效率和…

深度学习(Pytorch):Softmax回归

Softmax简介 Softmax回归是一个用于多类分类问题的线性模型&#xff0c;它是从Logistic回归模型演变而来的。Softmax回归与Logistic回归类似&#xff0c;但是输出不再是二元的&#xff0c;而是多类的。Softmax回归引入了softmax激活函数来将输出转换为合理的概率分布。与线性回…

HCIE-Cloud Computing LAB备考--第五题:规划--Type13练习--记忆技巧+默写

对LLD表,交换机接口表,ensp配置进行练习,如下图,设置答案和空白表,进行默写,汇总自己的容易犯的错误 LLD表默写思路 交换机接口配置表默写思路 以Type3为例,同颜色复制即可,共用ST.P0是A25,ST.P2是A21,FS是ST.P0是A21,ST.P2是A21。 ensp配置默写思路 特点: 所…

一步一步学习 Stable Diffusion

一步一步学习 Stable Diffusion 0. 背景1. 安装2. 汉化3. 安装 sd-webui-controlnet 插件4. 安装 sd-webui-segment-anything 插件5. 安装 ultimate-upscale 插件6. 安装 SadTalker 插件7. 下载和配置 VAE 模型8. 使用 ChilloutMix 模型99. 未完待续 0. 背景 网上看了很多 Sta…

priority_queue(优先级队列)

priority_queue 1. priority_queue的介绍及使用1.1 priority_queue的介绍1.2 priority_queue的使用1.2.1 constructor(构造)1.2.2 empty1.2.3 size1.2.4 top1.2.5 emplace1.2.6 push、pop、swap 1.3 数组中第K个大的元素 2.priority_queue的深度剖析及模拟实现 1. priority_que…

Makerbase SimpleFOC ESP32例程4 双电机闭环速度测试

Makerbase SimpleFOC ESP32例程4 双电机闭环速度测试 第一部分 硬件介绍 1.1 硬件清单 序号品名数量1ESP32 FOC V1.0 主板12YT2804电机2312V电源适配器14USB 线156pin杜邦线2 注意&#xff1a;YT2804是改装的云台无刷电机,带有AS5600编码器&#xff0c;可实现360连续运转。…

柔性作业车间调度

1柔性车间作业调度 个工件 要在 台机器 上加工。每个工件包含一道或多道工序&#xff0c;工序顺序是预先确定的&#xff0c;每道工序可以在多台不同加工机器上进行加工&#xff0c;工序的加工时间随加工机器的不同而不同。调度目标是为每道工序选择最合适的机器、确定每台机器…

【C语言】语言篇——数组和字符串

C站的小伙伴们&#xff0c;大家好呀&#x1f61d;&#x1f61d;&#xff01;我最近在阅读学习刘汝佳老师的《算法竞赛入门经典》&#xff0c;今天将整理本书的第三章——数组和字符串的一些习题&#xff0c;本章习题较多&#xff0c;下选取部分习题进行练习总结&#xff0c;在这…

200道面试题(附答案)

最近有不少小伙伴跑来咨询&#xff1a; 想找网络安全工作&#xff0c;应该要怎么进行技术面试准备&#xff1f;工作不到 2 年&#xff0c;想跳槽看下机会&#xff0c;有没有相关的面试题呢&#xff1f; 为了更好地帮助大家高薪就业&#xff0c;今天就给大家分享两份网络安全工…