基于python的Dubbo接口测试封装

环境

python 3.x

核心脚本
# DubboRequest.py
# -*- coding: utf-8 -*-
# @Time    : 2021/06/02 10:11
# @Author  : 软件测试技术
from Setting import config
import re
from loguru import logger
from functools import lru_cache
from kazoo.client import KazooClient
from urllib.parse import unquote
import telnetlib
import json
import urllib
import random
import sys
import os
from functools import reduce

sys.path.append(
    reduce(lambda x, _: os.path.dirname(x), list(range(1, 4)), __file__))


@lru_cache(maxsize=10)
class Dubbo(telnetlib.Telnet):
    prompt = 'dubbo>'
    coding = 'utf-8'

    def __init__(self, host=None, port=0, timeout=10):
        super().__init__(host, port, timeout)
        self.write(b'\n')

    def command(self, flag, str_=""):
        data = self.read_until(flag.encode())
        self.write(str_.encode() + b"\n")
        return data

    def invoke(self, service_name, method_name, arg):
        arg_str = None

        if isinstance(arg, (dict, list)):
            arg_str = json.dumps(arg)
        if isinstance(arg, tuple):
            arg_str = str(arg).replace("(", "").replace(")", "")

        command_str = "invoke {0}.{1}({2})".format(service_name, method_name,
                                                   arg_str)

        self.command(Dubbo.prompt, command_str)
        data = self.command(Dubbo.prompt, "")
        data = data.decode("utf-8", errors='ignore').split('\n')
        return data

    @logger.catch
    def queryDTO(self, service_name, method_name):
        command_str = f"ls -l {service_name}"

        self.command(Dubbo.prompt, command_str)
        data = self.command(Dubbo.prompt, "")
        data = data.decode("utf-8", errors='ignore').split('\n')
        print('Dto', data)
        for i in data:
            if method_name in i:
                p = re.compile(r'[(](.*?)[)]', re.S)  # 最小匹配
                dto = re.findall(p, i)
        if len(dto) == 1:
            return dto[0]
        else:
            logger.info(
                f"error>>>{service_name}.{method_name}`s dto not find!")


class DubboUtils(object):
    def __init__(self, zk_service, interface):
        self.zk_service = zk_service
        self.interface = interface

    @lru_cache(maxsize=10)
    def _get_dubbo(self, server_name):
        """
        获取单个dubbo服务的,这里可能要根据,
        :param server_name:服务名
        :return:{"service": service, "paths": paths, "method": method}
        """
        zk = KazooClient(hosts="{}".format(self.zk_service))
        zk.start()
        urls = []
        service_list = zk.get_children("dubbo")
        for i in service_list:
            if server_name in i:
                try:
                    # 获取服务发布方
                    providers = zk.get_children(
                        "/dubbo/{}/providers".format(i))
                    if providers:
                        for provider in providers:
                            url = urllib.parse.unquote(provider)
                            if url.startswith('dubbo:'):
                                urls.append(url.split('dubbo://')[1])
                except Exception as e:
                    logger.error(e)
        paths = []
        for i in urls:
            try:
                path, temp = i.split('/', 1)
                service = temp.split('?')[0]
                method = temp.split('methods=')[1].split('&')[0].split(',')
                paths.append(path)
            except Exception as e:
                logger.error(e)
                return None

        services = {"service": service, "paths": paths, "method": method}
        return services

    @logger.catch
    def requests_dubbo(self, method, param):
        """
        请求dubbo接口
        :param method: dubbo接口的方法
        :param param: 请求参数
        :return:
        """
        res = self._get_dubbo(self.interface)

        if res == None:
            return {"result": "fail", "data": "该service查询不到对应的信息"}
        else:
            methods = res.get("method")
            if method not in methods:
                raise NameError(f"{method} not in {methods}")

            paths = res.get("paths")

            if len(paths) > 1:
                paths = paths[random.randint(0, len(paths) - 1)]
                # paths = paths[-1]
            else:
                paths = paths[0]

            ip, port = paths.split(":")

            con = Dubbo(ip, port)
            # param['class'] = con.queryDTO(self.interface,method)

            logger.info(
                f"StratRun >>> ADDRESS:{ip} - PORT:{port} - SERVICE:{self.interface} -METHOD:{method}, PARAMS:\n {json.dumps(param, ensure_ascii=False)} "
            )
            result = con.invoke(service_name=self.interface,
                                method_name=method,
                                arg=param)

            logger.info(f"RESULT>>> {','.join(result)}")

            try:
                return {"result": "success", "data": json.loads(result[0])}
            except Exception as e:
                return {"result": e, "data": result}


class DubboRun:
    def __init__(self):
        self.zkAddress = "你们的zk地址"

    def run(self, service, dubboApi, dto, params):
    	"""
    	service-> 服务
    	dubboApi->方法
    	dto-> 入参类型 (不写这个参数 可能导致找不到该method的错误)
    	params-> 入参
    	"""
        params["class"] = dto
        myDubbo = DubboUtils(self.zkAddress, service)
        res = myDubbo.requests_dubbo(dubboApi, params)
        return res


if __name__ == '__main__':
    x = DubboRun()
    service = "com.xxx.xxxx.product.xxxxx.xxx.xxxxxxxxxxxxxxxxx"
	dto = "com.xxxx.xxxx.xxxx.xx.xxx.xxxxxxxx"
	dubboApi = "xxxxxxx"
	params = {"test": True, "logId": "test202020"}
	x.run(service=service,dubboApi=dubboApi,dto=dto,params=params)    

执行结果

2021-07-27 14:53:23.735 | INFO     | dubbo_req:requests_dubbo:133 - StratRun >>> ADDRESS:172.1xx.1xx.8x - PORT:20880 - SERVICE:com.xxxxxxxx.xxxxx.xxxx.xxx.xx.xxxxxxxx-METHOD:querySignListByPage, PARAMS:
 {"applyType": "ORG", "traceLogId": "apiTest2012070201"} 
2021-07-27 14:53:24.213 | INFO     | dubbo_req:requests_dubbo:137 - RESULT>>> {"result":{"currentPage":1,"dataList":[{"applyChannel":"","applyCode":"ssfdfdsfsdafasfdsdfasdfsdaffasdgf","beginDate":"2017-10-27 09:56:36","contractEntity":"","createdAt":"2017-10-27 09:56:36","endDate":"2020-08-01 00:00:00","id":"3631"}],"pageSize":1,"totalRows":1},"success":true}
,elapsed: 406 ms.
,dubbo>

—over—

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件测试技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值