• RPC 接口测试技术 —— websocket 自动化测试实践!


    WebSocket 是一种在单个 TCP 连接上进行全双工通信 (Full Duplex 是通讯传输的一个术语。通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输( A→B 且 B→A )。指 A→B 的同时 B→A,是瞬时同步的) 的协议。

    WebSocket 通信协议于 2011 年被 IETF 定为标准 RFC 6455,并由 RFC7936 补充规范。WebSocket API (WebSocket API 是一个使用 WebSocket 协议的接口,通过它来建立全双工通道来收发消息) 也被 W3C 定为标准。

    而 HTTP 协议就不支持持久连接,虽然在 HTTP1.1 中进行了改进,使得有一个 keep-alive,在一个 HTTP 连接中,可以发送多个 Request,接收多个 Response。

    但是在 HTTP 中 Request = Response 永远是成立的,也就是说一个 request 只能有一个 response。而且这个 response 也是被动的,不能主动发起。

    websocket 常用于社交 / 订阅、多玩家游戏、协同办公 / 编辑、股市基金报价、体育实况播放、音视频聊天 / 视频会议 / 在线教育、智能家居与基于位置的应用。

    websocket 接口不能使用 requests 直接进行接口的调用,可以依赖第三方库的方式来实现调用,以下内容介绍如何调用第三方库实现 websocket 的接口自动化测试。

    实战

    使用 python 语言实现 websocket 的接口自动化

    环境准备

    1. 安装 pyhton3 环境下载需要的运行库 2. 下载需要的运行库 pip install websocket-client

    实战演示

    • 连接 websoket 服务器
    1. import logging
    2. from websocket import create_connection
    3. logger = logging.getLogger(__name__)
    4. url = 'ws://echo.websocket.org/' #一个在线的回环websocket接口,必须以websocket的方式连接后访问,无法直接在网页端输入该地址访问
    5. wss = create_connection(url, timeout=timeout)
    • 发送 websocket 消息
    1. wss.send('Hello World')
    • 接收 websocket 消息
    1. res = wss.recv()
    2. logger.info(res)
    • 关闭 websocket 连接
    1. wss.close()
    • websocket 第三方库的调用不支持直接发送除字符串外的其他数据类型,所以在发送请求之前需要将 Python 结构化的格式,转换为成为字符串类型或者 json 字符串后,再发起 websocket 的接口请求
    1. #待发送的数据体格式为:
    2. data= {
    3. "a" : "abcd",
    4. "b" : 123
    5. }
    6. # 发送前需要把数据处理成 json 字符串
    7. new_data=json.dumps(data,ensure_ascii=False)
    8. wss.send(new_data)
    9. ```
    10. - 接收的数据体的处理:如果接口定义为 json 的话,由于数据的传输都是字符串格式的,需要对接收的数据体进行转换操作
    11. ```
    12. # 接收的数据体的格式也为字符串
    13. logger.info(type(res)) # <class 'str'>
    14. ```
    15. 对于响应内容进行格式转换处理:
    16. ```
    17. def load_json(base_str):
    18. if isinstance(base_str, str):
    19. try:
    20. res = json.loads(base_str)
    21. return load_json(res)
    22. except JSONDecodeError:
    23. return base_str
    24. elif isinstance(base_str, list):
    25. res = []
    26. for i in base_str:
    27. res.append(load_json(i))
    28. return res
    29. elif isinstance(base_str, dict):
    30. for key, value in base_str.items():
    31. base_str[key] = load_json(value)
    32. return base_str
    33. return base_str
    34. ```
    35. - websocket 接口自动化测试,二次封装 demo 展示
    36. web_socket_util.py 封装 websocket 接口通用操作:
    37. ```
    38. import logging
    39. import json
    40. from websocket import create_connection
    41. logger = logging.getLogger(__name__)
    42. class WebsocketUtil():
    43. def conn(self, uri, timeout=3):
    44. '''
    45. 连接web服务器
    46. :param uri: 服务的url
    47. :param timeout: 超时时间
    48. :return:
    49. '''
    50. self.wss = create_connection(uri, timeout=timeout)
    51. def send(self, message):
    52. '''
    53. 发送请求数据体
    54. :param message: 待发送的数据信息
    55. :return:
    56. '''
    57. if not isinstance(message, str):
    58. message = json.dumps(message)
    59. return self.wss.send(message)
    60. def load_json(self, base_str):
    61. '''
    62. 进行数据体的处理
    63. :param base_str: 待处理的数据体
    64. :return:
    65. '''
    66. if isinstance(base_str, str):
    67. try:
    68. res = json.loads(base_str)
    69. return self.load_json(res)
    70. except JSONDecodeError:
    71. return base_str
    72. elif isinstance(base_str, list):
    73. res = []
    74. for i in base_str:
    75. res.append(self.load_json(i))
    76. return res
    77. elif isinstance(base_str, dict):
    78. for key, value in base_str.items():
    79. base_str[key] = self.load_json(value)
    80. return base_str
    81. return base_str
    82. def recv(self, timeout=3):
    83. '''
    84. 接收数据体信息,并调用数据体处理方法处理响应体
    85. :param timeout: 超时时间
    86. :return:
    87. '''
    88. if isinstance(timeout, dict):
    89. timeout = timeout["timeout"]
    90. try:
    91. self.settimeout(timeout)
    92. recv_json = self.wss.recv()
    93. all_json_recv = self.load_json(recv_json)
    94. self._set_response(all_json_recv)
    95. return all_json_recv
    96. except WebSocketTimeoutException:
    97. logger.error(f"已经超过{timeout}秒没有接收数据啦")
    98. def settimeout(self, timeout):
    99. '''
    100. 设置超时时间
    101. :param timeout: 超时时间
    102. :return:
    103. '''
    104. self.wss.settimeout(timeout)
    105. def recv_all(self, timeout=3):
    106. '''
    107. 接收多个数据体信息,并调用数据体处理方法处理响应体
    108. :param timeout: 超时时间
    109. :return:
    110. '''
    111. if isinstance(timeout, dict):
    112. timeout = timeout["timeout"]
    113. recv_list = []
    114. while True:
    115. try:
    116. self.settimeout(timeout)
    117. recv_json = self.wss.recv()
    118. all_json_recv = self.load_json(recv_json)
    119. recv_list.append(all_json_recv)
    120. logger.info(f"all::::: {all_json_recv}")
    121. except WebSocketTimeoutException:
    122. logger.error(f"已经超过{timeout}秒没有接收数据啦")
    123. break
    124. self._set_response(recv_list)
    125. return recv_list
    126. def close(self):
    127. '''
    128. 关闭连接
    129. :return:
    130. '''
    131. return self.wss.close()
    132. def _set_response(self, response):
    133. self.response = response
    134. def _get_response(self) -> list:
    135. return self.response
    136. ```
    137. test_case.py websocket 接口自动化测试用例:
    138. ```
    139. class TestWsDemo:
    140. def setup(self):
    141. url = 'ws://echo.websocket.org/'
    142. self.wss = WebsocketUtil()
    143. self.wss.conn(url)
    144. def teardown(self):
    145. self.wss.close()
    146. def test_demo(self):
    147. data = {"a": "hello", "b": "world"}
    148. self.wss.send(data)
    149. res = self.wss.recv()
    150. assert 'hello' == res['a']
    151. ```
    152. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
    153. 在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

    最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!

    软件测试面试文档

    我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
     

    在这里插入图片描述

  • 相关阅读:
    Linux 安装maven两种方式(使用yum或手动安装)
    Javascript知识【省市二级联动】重点
    Python基础--字典
    STL函数对象---C++
    SSM实验室门禁管理系统毕业设计-附源码221252
    运维困局下确保系统稳定的可行性
    Debezium系列之:使用逻辑命名空间为不同的表做个性化设置
    云服务的划分IaaS,PaaS,SaaS 的区别
    【Java中23种面试常考的设计模式之外观模式(Facade)---结构型模式】
    js的闭包例题
  • 原文地址:https://blog.csdn.net/m0_58026506/article/details/133893987