在当今的分布式系统中,远程过程调用(RPC)协议已成为不同系统、服务之间通信的桥梁。而对于测试工程师来说,如何高效地实现基于RPC协议的接口自动化测试,成为保障系统稳定性和性能的关键问题。
那么,如何通过Python来实现基于RPC协议的接口自动化测试?这背后又有哪些技术细节和最佳实践值得我们关注?
RPC协议允许程序通过网络执行远程服务上的函数调用,就像在本地调用一样。这使得RPC在微服务架构中尤为重要。通过Python,我们可以模拟客户端发送请求、服务器处理请求,并返回结果,从而实现全面的接口测试。例如,在一个基于gRPC的微服务架构中,Python可以通过gRPC框架生成客户端和服务器端代码,从而实现高效的自动化测试。
01 什么是RPC
RPC(Remote Procedure Call)远程过程调用协议是一个用于建立适当框架的协议。从本质上讲,它使一台机器上的程序能够调用另一台机器上的子程序,而不会意识到它是远程的。
RPC 是一种软件通信协议,一个程序可以用来向位于网络上另一台计算机的程序请求服务,而不必了解网络的细节。RPC 被用来像本地系统一样调用远程系统上的其他进程。过程调用有时也被称为函数调用或子程序调用
02 RPC框架
RPC本身是一套协议规范,遵循这一套规范实现的框架比较流行的有以下几个:
-
grpc框架
gRPC是由 google开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于HTTP/2协议标准而设计,同时支持大多数流行的编程语言。gRPC基于 HTTP/2协议传输
-
dubbo框架
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:
① 面向接口的远程方法调用
② 智能容错和负载均衡
③ 服务自动注册和发现
-
thrift框架
Thrift是一种接口描述语言和二进制通讯协议。原由Facebook于2007年开发,2008年正式提交Apache基金会托管,成为Apache下的开源项目。
Thrift是一个RPC通讯框架,采用自定义的二进制通讯协议设计。相比于传统的HTTP协议,效率更高,传输占用带宽更小。另外,Thrift是跨语言的
-
Hetty 框架
Hetty 是一款构建于 Netty 和 Hessian 基础上的高性能的 RPC 框架
Hessian 是一款基于 HTTP 协议的 RPC 框架,采用的是二进制 RPC 协议,非常轻量级 ,且速度较快。
Netty 是一款基于事件驱动的 NIO 框架,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Hetty 客户端完全由 Hessian 实现,只是使用 Netty 重新实现了服务端
03 基于grpc框架服务的接口测试
01 创建一个grpc服务接口
注意在公司里你们的grpc服务可能并不是采用python去实现的,课上咱们为了测试grpc的接口,使用python先创建grpc的服务接口。
-
安装依赖库
-
创建grpc接口协议文档
在项目下创建一个grpc_study包,包下创建一个add.proto文件,将下述内容复制进去
-
生成服务代码
终端下进入proto文件所在目录,执行下述命令:
-
创建服务端
import grpc
import add_pb2
import add_pb2_grpc
from concurrent import time
import futures
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class AddServer(add_pb2_grpc.AddServiceServicer):
def add(self, request, context):
print(f'a:{request.a},b:{request.b}')
c = request.a+request.b
return add_pb2.AddReply(res=c)
def server():
# os.system('set GRPC_VERBOSITY=debug')
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_pb2_grpc.AddServiceServicer_to_server(AddServer(),server)
server.add_insecure_port('[::]:33333')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
server()
02 调用grpc接口客户端
以下代码就是调用第一步中的grpc接口的
import grpc
import add_pb2
import add_pb2_grpc
def run():
with grpc.insecure_channel('127.0.0.1:9999') as channel:
client = add_pb2_grpc.AddServiceStub(channel)
res = client.add(add_pb2.AddRequest(a=1,b=3))
print(res.res)
if __name__ == '__main__':
run()
03 接口框架中适配grpc封装
1、封装底层channel初始化
在config目录下创建grpc.yml,其中写上grpc接口的地址:
在common目录下的client中增加下述代码:
在conftes.py中增加下述代码:
2、封装grpc接口调用
在api包下创建一个grpcapi的包,将grpc的定义proto文件拷贝进去,然后在终端下进入grpcapi目录执行下述命令
该目录下文件如下:
修改add_pb2_grpc.py中的导入如下:
根据上述代码封装接口调用,创建一个api_client.py,写上如下代码就是grpc提供的add接口的调用方法
from apicapi import add_pb2_grpc, add_pb2
from common.client import GrpcChannel
def add(a, b):
client = add_pb2_grpc.AddServiceStub(GrpcChannel.channel)
res = client.add(add_pb2.AddRequest(a=a, b=b))
return res.res
3、编写grpc接口测试用例
在testcases包下创建一个grpcapi包,创建一个test_grpc_api.py,编写针对add接口的测试用例如下:
from api.grpcapi.api_Client import add
class TestGrpcAdd:
def test_add(self):
res = add(a=2, b=3)
assert res==5
执行测试
04 基于dubbo框架服务的接口测试
dubbo服务管理地址:
http://**.***.**.***:****/dubbo-admin-2.6.0
用户名和密码都是root
01 dubbo服务管理简单使用
先设置为中文,右侧选择语言
选择服务治理-->服务
点开MarketService,再点ip和端口,打开如下:
02 实战接口说明
第1步里我们看到了两个接口,exchange和lottery,下面是这两个接口的业务说明
-
exchange
业务是积分兑换,该接口的参数是一个对象,对象类型对应后台java代码中的某个类cn.testfan.dubbo.model.ExchangeRequest,这个类对象对应的属性如下,这些属性其实就是我们的参数
-
lottery
业务是抽奖,参数有两个,都是数字,没有参数名称,按照顺序,第一个表示参与的活动id,第二个表示用户id
03 python调用dubbo接口
-
安装第三方库
-
dubbo接口调用
from dubbo_client import DubboClient
from dubbo.codec.encoder import Object
# 创建Dubbo客户端实例
market = DubboClient(interface='cn.testfan.dubbo.service.MarketService',
host='localhost',
port=20880,
dubbo_version='2.6.2',
version='1.0'
)
# 调用lottery接口,该接口的入参(3, 10001),按照顺序对应
res = market.call('lottery', (3, 10001))
print(res) # lottery接口发起的结果
# 实例化一个exchange接口需要的参数对象
# 第一个参数指的是该对象对应的java后台的类型
# values是该类型的对象属性
ExchangeRequest = Object("cn.testfan.dubbo.model.ExchangeRequest",
values={
"userId": 10001,
"activityId": 2,
"awardId": 4,
"exchangeNum": 1
})
res = market.call('exchange', ExchangeRequest)
print(res) # exchange接口发起的结果
04 接口框架中适配dubbo封装
1、封装底层dubbo初始化
在config目录下创建dubbo.yml文件,写上如下内容
在client.py里增加下述代码
2、封装api层
dubbo接口通常是按照服务进行划分,一个服务下有多个接口,针对该服务创建对象,然后调用各个接口。
在api包下创建dubboapi的包,针对market服务创建一个market_api.py文件,写上如下代码:
from dubbo.client import DubboClient
from dubbo.codec.encoder import Object
from common.client import BaseDubbo
class MarketService(BaseDubbo):
def __init__(self):
super().__init__()
self.service = DubboClient(
interface="cn.testfan.dubbo.service.MarketService",
host=self.host,
dubbo_version=self.dubbo_version,
version=self.version
)
def lottery(self, activity_id, user_id):
return self.send('lottery', activity_id, user_id)
def exchange(self, values):
# {"userId": 10001, "activityId": 2, "awardId": 4, "exchangeNum": 1}
ExchangeRequest = Object("cn.testfan.dubbo.model.ExchangeRequest", values=values)
return self.send('exchange', ExchangeRequest)
3、测试用例层
在testcases包下创建dubboapi包,在其下创建test_market_service.py,写上如下代码
from api.dubboapi.market_api import MarketService
class TestMarketService:
def setup_class(self):
self.market = MarketService()
print('market成功')
def test_lottery(self):
# self.market = MarketService()
res = self.market.lottery(3, 10001)
assert res['message'] == '活动已结束'
def test_exchange(self):
values = {
"userId": 10001,
"activityId": 2,
"awardId": 4,
"exchangeNum": 1
}
res = self.market.exchange(values)
assert res['message'] == '该用户无积分'
执行测试
随着微服务架构的普及,RPC协议成为了服务间通信的主流方式。然而,这也带来了新的测试挑战。接口自动化测试的重要性愈发凸显,它不仅能提高开发效率,还能在系统的早期阶段发现潜在问题,从而降低生产环境中的风险。
想进一步掌握Python在RPC协议中的应用?市面上有许多优质的在线课程和书籍,能够帮助你快速上手,成为接口自动化测试的高手。
Python在实现基于RPC协议的接口自动化测试中展现了强大的灵活性和高效性。通过掌握这一技术,测试人员可以更好地保障分布式系统的稳定性和可靠性,确保各个服务之间的通信顺畅无误。