接口测试之主流协议测试合集(python版)

http://t.csdn.cn/U4WHz

01 TCP/IP四层模型&OSI七层模型

1. OSI,TCP/IP,五层协议的体系结构,以及各层协议

  • OSI分层 (7层):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

  • TCP/IP分层(4层):网络接口层、 网际层、运输层、 应用层。

  • 网络接口层:ip

  • 网际层:TCP、UDP

  • 运输层

  • 应用层

  • 五层协议 (5层):物理层、数据链路层、网络层、运输层、 应用层。

  • 每层作用

    • 物理层:传输二进制比特流
    • 数据链路层:负责将上层数据封装成帧
    • 网络层:负责路由寻址和广播 ;广播:发送消息和接收消息
      *传输层:负责建立一个可靠的端到端的连接;端到端:发送到接收 ;过程:建立、维护、撤销(拆除)
    • 会话层:负责建立维护拆除会话,为端应用之间提供控制功能(可靠性)
    • 表示层:完成对传输数据格式转换:格式化;发:加密;接:解密;发:压缩,接:解压缩
    • 应用层:对应用软件提供网络支持
      在这里插入图片描述

02 IP协议

1. IP地址: 所有主机都会分配一个IP地址(不重复) ipv4 4位组成0-255,网关,子掩码。

2.端口: 为了确定主机上的应用程序。0-65535能使用的端口1024-65535
3.域名: 在万维网上注册的网站名称。通过域名解析变成ip地址。

03 TCP协议

1. 定义

  • TCP协议又称传输控制协议,是面向连接的可靠传输;
  • 发送⽅和接收⽅的成对的两个socket之间必须建⽴连接,以便在TCP协议的基础上进⾏通信,当⼀个socket(通常都是server socket)等待建⽴连接时,另⼀个socket可以要求进⾏连接,⼀旦这两个socket连接起来,它们就可以进⾏双向数据传输,双⽅都可以进⾏发送 或接收操作

2. 特点

  • ⾯向连接的协议,在socket之间进⾏数据传输之前必然要建⽴连接,所以在TCP中需要连
    接时间。
  • TCP传输数据⼤⼩限制,⼀旦连接建⽴起来,双⽅的socket就可以按统⼀的格式传输⼤的数据。
  • TCP是⼀个可靠的协议,它确保接收⽅完全正确地获取发送⽅所发送的全部数据。

3.应用场景

  • IM及时通信、游戏、工控、物联网、微服务

4. 测试脚本

	'''
	1. 序列化: 将数据结构或对象转换成二进制串的过程
    	1) 获取私有协议说明文档
    	2)google的protobuf作为序列化工具
        	(1)安装protoc工具
        	(2)构造私有协议的proto文件
        	(3)将proto编译成.py文件
           			 `protoc --python_out=生成的py文件存放目录 xxx.proto` 读入xxx.proto,输出python文件到一个指定目录下
           			 `protoc --java_out=生成的jar文件存放目录 xx.proto`
        	(4)在测试脚本中使用编译生成的.py
   2. 创建套接字
   3. 连接服务器 socket.con
   4. 构造请求并进行序列化:SerializeToString()
   5. 发送数据:socket.sendall()
   6. 接受数据,并进行反序列化操作:ParseFromString
   7. 响应断言
	'''
import unittest
import socket
import json
from protocol_test.tcp import data_pb2
class TestTcpDemo(unittest.TestCase):

    def setUp(self) -> None:
        pass
    def setUpClass(cls) -> None:
        pass
    def tearDown(self) -> None:
        pass

    def tearDownClass(cls) -> None:
        pass

    def test_login_01(self):
        # 接口地址
        self.server = ('127.0.0.1','8889')
        # 创建套接字
        self.s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        # 连接服务器
        self.s.connect(self.server)

        # 发送数据
        self.send_data = data_pb2.SendData()
        self.revc_data = data_pb2.RevcData()

        # 构造请求
        self.send_data.control = 1
        self.send_data.action = 1
        self.userinfo = {
            "username": "test001",
            "passwd": "123456",
        }

        self.send_data.user_data = json.dumps(self.userinfo)

        # 序列化,二进制字符串
        self.send_data = self.send_data.SerializeToString()

        # 发送数据
        self.s.sendall(self.send_data)

        # 接受数据
        self.ret = self.revc_data(65536)

        # 反序列化
        self.revc_data.ParseFromString(self.ret)

        # 断言
        self.assertEqual(200,self.revc_data.status)

        # 断开连接
        self.s.close()

04 UDP协议

1. 定义

  • UDP是User Datagram Protocol的简称,是⼀种⽆连接的协议;
  • 每个数据报都是⼀个独⽴的信息,包括完整的源地址或⽬的地址;
  • 它在⽹络上以任何可能的路径传往⽬的地,因此能否到达⽬的地,到达⽬的地的时间以及内容的正确性都是不能被保证的。

2.特点

  • 每个数据报中都给出了完整的地址信息,因此⽆需要建⽴发送⽅和接收⽅的连接。
  • UDP传输数据时是有⼤⼩限制的,每个被传输的数据报必须限定在64KB之内。
  • UDP是⼀个不可靠的协议,发送⽅所发送的数据报并不⼀定以相同的次序到达接收⽅。

3.TCP和UDP的对比

  • TCP,可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。
  • UDP,不可靠,差错控制开销较小,传输大小限制在64K以下,不需要建立连接。

4. UDP服务端

import socket
def main():
    #1.创建套接字
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # tcp为SOCK_STREAM
    # 2. 绑定一个本地信息
    localAddr = ('169.254.148.206', 8001)  # 自己电脑的ip以及port号,其他的不行
    udp_socket.bind(localAddr)
    # 3. 接收数据
    while 1:
        recv_data = udp_socket.recvfrom(65536) #存储的是一个元组(接收到的数据,(发送方的ip,port))  Tuple[bytes, _RetAddress]
        recv_msg = recv_data[0]  # 接收的数据
        send_addr = recv_data[1]  # 发送方的地址
        # 4.打印接收到的数据
        print('{}:{}'.format(str(send_addr), recv_msg.decode('utf-8')))
        if not recv_msg:
            break
    # 5.关闭套接字
    udp_socket.close()
if __name__ == '__main__':
    main()

5. UDP客户端

import socket
def main():
    # 1.创建一个udp套接字
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    addr = ('169.254.148.206',8001)
    while True:
        # 从键盘输入数据
        send_data = input('请输入要发送的数据:')
        # 如果输入exit,就退出程序
        if send_data =='exit':
            break
        # 可以使用套接字发送数据
        #upd_scoket.sendto('ahahahha','对方的ip及端口')
        udp_socket.sendto(send_data.encode('utf-8'),addr)
    # 关闭套接字
    udp_socket.close()
if __name__ == '__main__':
    main()

05 web services协议

https://www.w3school.com.cn/ws.asp
1. Web Services定义:

  • 一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互

2. web services组成元素:

  • SOAP(简易对象访问协议)
    • 一种使应用程序有能力通过 HTTP 交换信息的基于 XML 的简易协议
    • 一种用于访问 web service 的协议
  • UDDI(通用描述、发现及整合)
    • 基于 XML 的跨平台的描述规范
    • 用于存储有关 web services 的信息的目录
  • WSDL(Web services 描述语言)
    • 基于 XML 的用于描述 网络服务以及如何访问 Web Services 的语言;
    • 可描述 web service,连同用于 web service 的消息格式和协议的细节。

3. 基本工作原理

  • web服务提供者设计实现Web服务,并将调试正确后的Web服务通过Web服务中介者发布,并在UDDI注册中心注册; (发布)
  • Web服务请求者向Web服务中介者请求特定的服务,中介者根据请求查询UDDI注册中心,为请求者寻找满足请求的服务; (发现)
  • Web服务中介者向Web服务请求者返回满足条件的Web服务描述信息,该描述信息用WSDL写成,各种支持Web服务的机器都能阅读;(发现)
  • 利用从Web服务中介者返回的描述信息生成相应的SOAP消息,发送给Web服务提供者,以实现Web服务的调用;(绑定)
  • Web服务提供者按SOAP消息执行相应的Web服务,并将服务结果返回给Web服务请求者。(绑定)

4. python实现

  • 安装suds
    pip install suds -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
    

在这里插入图片描述

import unittest
from suds.client import Client
import json
import sys
from time import sleep
import logging


class WebServiceApi(Client):
    def __init__(self, url, **kwargs):
        super().__init__(url, **kwargs)


class TestWebServiceDemo(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        pass

    def setUp(self) -> None:
        pass

    def tearDown(self) -> None:
        pass

    @classmethod
    def tearDownClass(cls) -> None:
        pass

    # 无参形式
    def testmobilePhone001(self):
        global res
        mp_url = 'http://ws.webxml.com.cn/webservices/MobileCodeWS.asmx?wsdl'
        wsa = WebServiceApi(mp_url)
        for i in range(3):
            try:
                res = wsa.service.getDatabaseInfo()
                if res:
                    body = json.dumps(res[0], ensure_ascii=False)
                    self.assertTrue(body not in ([], '', None))
                    self.assertTrue('安徽' in body)
                    break
                else:
                    sleep(15)
            except Exception as e:
                logging.warning("第%s次请求失败!信息:%s" % (i + 1, e))
        else:
            sys.exit('环境异常')

    # 有参形式-正常场景
    def testmobilePhone002(self):
        mp_url = 'http://ws.webxml.com.cn/webservices/MobileCodeWS.asmx?wsdl'
        wsa = WebServiceApi(mp_url)
        for i in range(3):
            res = wsa.service.getMobileCodeInfo(mobileCode='13588888888')
            body = json.dumps(res, ensure_ascii=False)
            if body:
                self.assertTrue('浙江移动' in str(body))
                break
            else:
                sleep(15)
        else:
            sys.exit('请求接口三次失败')

    # 有参形式-异常场景
    def testmobilePhone003(self):
        mp_url = 'http://ws.webxml.com.cn/webservices/MobileCodeWS.asmx?wsdl'
        wsa = WebServiceApi(mp_url)
        for i in range(3):
            res = wsa.service.getMobileCodeInfo(mobileCode='19988888888')
            body = json.dumps(res, ensure_ascii=False)
            print(body)
            if body:
                self.assertTrue('没有此号码记录' in body)
                break
            else:
                sleep(15)
        else:
            sys.exit('请求3次接口均失败')

06 HTTPS协议

1. 定义

  • 身披SSL外壳的HTTP。HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。

2. 特点

  • 基于HTTP协议,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护,如:内容加密,验证身份,保护数据完整性,混合加密,数字摘要,数字签名技术
import unittest
import requests
import sys


class TestFinance(unittest.TestCase):
    http_url = 'http://api.k780.com'
    https_url = 'https://sapi.k780.com'

    @classmethod
    def setUpClass(cls) -> None:
        pass

    def setUp(self) -> None:
        pass

    def tearDown(self) -> None:
        pass

    @classmethod
    def tearDownClass(cls) -> None:
        pass

    def request(self, url, method, data, headers=None):
        for i in range(3):
            try:
                ret = requests.request(method=method, url=url, data=data, headers=headers)
                status = ret.status_code
                body = ret.json()
                return status, body
            except requests.exceptions as e:
                print("调用接口第(%s)次失败信息:%s" % (i + 1, e))
        else:
            sys.exit('调用->%s三次均失败' % data['app'])

# 接口地址:https://www.nowapi.com/api/finance.rate
    def test_finance_rate(self):
        params = {
            'app': 'finance.rate',
            'scur': 'HKD',
            'tcur': 'CNY',
            'appkey': '65550',
            'sign': 'f9d448dab9b6e7590140279ccffe3c23',
            'format': 'json',
        }
        status, body = self.request(self.https_url, 'post', data=params)
        print(body)
        self.assertEqual(status, 200, '状态码为200')
        if body:
            self.assertTrue(body['success'] != '0', 'success==1')
            self.assertTrue(body['result']['rate'] not in (None, ""))
        else:
            print(status)

    def test_weather_future(self):
        params = {
            'app': 'weather.future',
            'weaId': '1',
            'appkey': '65550',
            'sign': '77f6e1bd4e22de810987fcb8423941a5',
            'format': 'json',
        }
        status, body = self.request(self.https_url, 'post', data=params)
        print(body)
        self.assertEqual(body['success'], '1')
        self.assertIn('北京', str(body['result']), '返回北京天气预报')

07 dubbo协议

7.1 RPC&dubbo

1. rpc: 远程过程调用,通俗地讲RPC就是要解决远程服务间的调用问题,也就是管理服务配置并提供便捷可靠高效的服务间调用。
2. dubbo:是一个分布式的服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。既是框架也是协议
3. rpc和dubbo的关系:rpc是一种编程细想或者是通信方式(RPC不是协议),而dubbo是rpc的一种实现方式,dubbo基于tcp协议开发

7.2 dubbo框架概念

在这里插入图片描述
1. 节点角色说明

  • Provider: 暴露服务的服务提供方。
  • Consumer: 调用远程服务的服务消费方。
  • Registry: 服务注册与发现的注册中心。
  • Monitor: 统计服务的调用次调和调用时间的监控中心。
  • Container: 服务运行容器。

2. 调用关系说明

  • 0.start. 服务容器负责启动,加载,运行服务提供者。
  • 1. register服务提供者在启动时,向注册中心注册自己提供的服务。
  • 2. subscribe 服务消费者在启动时,向注册中心订阅自己所需的服务。
  • 3. notify: 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  • 4. invoke:服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  • 5. count 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

7.3 telnetlib方式实现dubbo测试

1. 模块封装

import logging
from telnetlib import Telnet

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class DubboApi(Telnet):
    prompt = 'dubbo>'

    def __init__(self, host, port):
        # 1. 创建telnet对象
        super().__init__((host, port))
        self.write(b'\n')

    def command(self, flag, _command=''):
        data = self.read_until(flag.encode())
        # 3. 用write发送dubbo请求
        self.write(_command.encode() + b'\n')
        return data

    def invoke(self, service_name, method_name, args=None):
        if args is None:
            args = []
        if not args:
            cmd_string = "invoke {0}.{1}.()".format(
                service_name, method_name
            )
        else:
            cmd_string = "invoke {0}.{1}.({2})".format(
                service_name, method_name, args
            )
        invoke_count = 0
        while invoke_count<5:
            self.command(DubboApi.prompt, cmd_string) # 读取到标志位
            ret = self.command(DubboApi.prompt, "")
            body = ret.decode().split('\r\n')[0] # 解码
            # 4. 获取返回信息
            # read_until()当结果中存在想要的信息时返回。
            # read_some() 只要有结果就返回。
            # read_very_lazy():返回缓冲区中的数据。
            if body:
                return body
            else:
                invoke_count += 1
        else:
            logging.error("调用dubbo接口超过五次,调用失败")


    # 退出telnet
    def logout_host(self):
        self.write(b"exit\n")
        logging.info("登出成功")

2. 测试用例

import unittest
from dubbo.dubbo_api import DubboApi


class TestTelnetLib(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        pass

    def setUp(self) -> None:
        pass

    def tearDown(self) -> None:
        pass

    @classmethod
    def tearDownClass(cls) -> None:
        pass

    def test_dubbo_demo01(self):
        dubbo_client = DubboApi('127.0.0.1', 8090)
        ret = dubbo_client.invoke(
            'com.dubbo.api.DemoService',
            'method',
            'param1,param2'
        )
        self.assertEqual('200', ret['status'], '返回200')


if __name__ == '__main__':
    unittest.main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值