微服务契约测试-Pact

一、微服务概述

本质是一种架构模式,是SOA(面向服务型架构)的一种变体,每个服务围绕具体的业务进行构建,可以独立部署;每个服务运行于独立的进程中,服务间用Rest API进行通讯。

单体架构

优点
1、团队组织结构简单,易于集中管理
2、开发进度一致,避免重复开发
3、所有功能都在本地,没有远程调用开销
缺点
效率低、维护困难、不够灵活、稳定性不好、扩展性不够

微服务优势与缺点

优势
1、解决单体式架构缺点
2、部署、回滚更加便捷
3、每个服务可以独立扩容
4、每个服务可以用适合的技术栈实现
5、可以用插件的形式更新系统,不必每次更新重新部署整个系统
6、对于业务数据可以用数据接口方式,方便后续发展业务数据的管理和迁移
缺点
1.每个子系统有独立的团队,增加团队交流成本,系统内部通信开销增加
2.分布式架构的自动化部署、项目测试、项目管理复杂度大大提高
3.代码重复,同业务代码无法封装成工具类进行调用

二、微服务测试

对测试影响:

1、每个微服务承担一定职责,尽可能小,又要达到一定规模
2、微服务间通过Rest API进行连接
3、每种服务不一定有界面,不一定能够从UI进行完整测试
4、微服务通常可以划分为更小的模块,可以考虑从不同的模块入手进行测试

微服务测试面临的挑战:

1、服务/模块之间复杂的依赖关系
2、不同的服务可能在不同的环境下运行
3、涉及多个服务的UI端到端测试容易出错
4、测试结果可能取决于网络稳定性
5、故障的分析复杂度随着服务增加而提高
6、与不同的开发团队之间的交流成本

微服务测试原则:

1、自动化
2、层次化(单元-接口-UI,粒度:细-粗,速度:快-慢)
3、可视化(测试结果可视化)

微服务主要测试方法:

1、单元测试(验证服务内部业务、通信)
2、集成测试(验证服务外部数据、通信)
3、组件测试(微服务是否起到预期作用)
4、契约测试(组件外部,关联的组件间契约的正确性)
5、端到端测试(整个系统的功能是否满足,UI)
6、探索测试

三、微服务契约测试(链路追踪)

什么是契约测试:

基于契约,对消费者和生产者间的协作验证。本质是验证生产者提供的内容是否满足消费者的期望

契约概念:

请求
请求头、url、请求的动作、参数
响应
生产者服务对于前面请求的应答,包含响应的状态码、内容、错误描述等
元数据
对消费者和生产者之间的协作过程的描述,如:生产者/消费者名称、上下文及场景描述

契约类型:

1、消费者驱动的契约类型(CDC)
2、生产者驱动的契约类型
流程:
1、对消费者的业务逻辑进行验证时,先对其期望的响应做模拟提供者(Mock);并将请求(消费者)-响应(基于模拟提供者)的协作过程,记录为契约;
2、通过契约,对提供者进行回放,保证提供者所提供的内容满足消费者的期望。

契约测试价值:

验证生产者响应,但是保障的是消费者服务

契约测试设计:

工具:Pact

1、在生产者所面向的消费者项目代码中编写测试,期望响应设置于模拟的服务生产者上。
2、在测试运行时,模拟的服务将返回所期望的响应。请求和所期望的响应将会被写入到一个"pact"文件中。
3、pact文件中的请求随后在生产者上进行回放,并检查实际响应以确保其与所期望响应相匹配。——pact-verifier --provider-base-url=http://localhost:8000 --pact-url=consumer01-provider.json
在这里插入图片描述
在这里插入图片描述

'''
    pact-python契约测试示例
'''
import atexit
import unittest
import requests
from pact import Consumer,Provider

# 定义一个契约(pact),明确消费者与生产者,明确契约文件的存放路径
pact_demo=Consumer('consumer02').has_pact_with(Provider('provider'),pact_dir='./pacts')
# 服务启动
pact_demo.start_service()
#服务的注册
atexit.register(pact_demo.stop_service)
class PactDemo(unittest.TestCase):
    # 定义契约的内容
    def test_pact(self):
        # 定义预期的响应结果
        expected = {
            'name': 'xxxx',
            'age': 18
        }

        #定义契约的实际内容
        (pact_demo
         .given('test service')
         .upon_receiving('for pact')
         .with_request('get','/provider') #向生产者发送请求时,需要注意请求方法、路径、参数、头部信息等
         .will_respond_with(status=200,body={'first':'xx','second':'yy'})) #生产者在被请求之后返回的响应的结果。可以自己定义内容的

        # 基于requests库向pact发送请求,验证契约生成的结果是否正确 ,请求的实际上是pact自带的mock服务,端口默认是1234
        with pact_demo:
            resp = requests.get('http://localhost:1234/provider').json()
            print(resp)

        # 断言校验,判断预期结果是否与pact的结果相符合
        self.assertEqual(expected,resp)

if __name__ == '__main__':
    pd = PactDemo()
    pd.test_pact()

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>