python API自动化(Jsonpath断言、接口关联及加密处理)

JsonPath应用及断言 重要

        自动化要解决的核心问题 :进行自动测试-自动校验(进行结果的校验

  1. 主要能够通过这个方式提取数据
  2. 业务场景:断言 、接口关联

{key:value}网址:附:在线解析 JSONPath解析器 - 一个工具箱 - 好用的在线工具都在这里!

json的基本应用:\

        

格式: $路径

基础的应用【必须掌握的】
# 1. $.key 
$.name
# 2. $..key --- 从任意的目录去找
$.name

列表:可以通过下标去进行获取:从0开始
$.hobbies[2]

$..year  --- 所有的年

语法:
$.key[?(@.key==year)]

区间:左闭右开(后面的下标需要+1)
$.projects[0:1]




# 获取根目录下的子字段:获取用户名
$.name
# 获取根目录下的字典中的数据:获取地址中的城市("country": "USA")
$.address.country
# 获取根目录下的列表中的某个数据:获取教育经历
$.education[0]
# 获取根目录下的列表中的所有数据中的某个字段:获取教育经历中的年
$.education[0:].year
# 获取根目录下的列表中满足某个条件的数据:获取教育经历中的年等于2020 的数据,== \!=
$.education[?(@.year==2020)]
# 获取所有的数据
$.*

我们把数据放入pycharm中,在里面编写json代码

        

#  返回的数据类型都是列表格式【重点】
res = jsonpath.jsonpath(data, "$..year")
print(res)
print(type(res))

res = jsonpath.jsonpath(data, "$.name")
print(res)  # 列表
print(res[0])  # 下标获取某个值
print(type(res))

代码示例如下

import json

import requests
import jsonpath

# 案例:登录接口 :
# 接口请求的四要素:URL\ 请求方法 \请求参数\响应数据
#  URL
url = "http://shop-xo.hctestedu.com/index.php?s=/api/user/login"
# 请求参数-- 公共参数-- url
pulic_data = {"application": "app", "application_client_type": "weixin"}
# 请求参数-- body (你的body数据是要以json进行提交,参数:json)
data = {"accounts": "hami", "pwd": "123456", "type": "username"}
# 请求头
header = {'Content-Type': 'application/json; charset=utf-8'}
#  请求头是json,所以数据类型需要转
json_data = json.dumps(data)

# --------------------发送接口请求---------------------------
res = requests.post(url, params=pulic_data, headers=header,data=json_data) # 正确的演示

# --------------------获取响应数据---------------------------
print(res.json())
# print("响应的数据类型:", res.headers)


# --------------------获取数据进行断言处理---------------------------
#  失败案例
exData = "登录成功"
# SjData = jsonpath.jsonpath(res.json(),"$.msg")   #  错误的案例
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]
# print(SjData)
assert exData == SjData, "期望结构是:{0},实际结果是:{1}".format(exData, SjData)

示例2:

        

import requests
import jsonpath
import json
# 案例一:
url = "http://shop-xo.hctestedu.com/index.php?s=/api/user/login"
public_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hami", "pwd": "123456", "type": "username"}
res = requests.post(url=url, params=public_data, data=data)
# ----------------------------------------
# 获取响应数据
result1 = res.json() # 以字典的格式获取
result2 = res.text # 以文本的格式获取
print(type(result1)) # 字典 <class 'dict'>
print(type(result2)) # 字符串 <class 'str'>
# 实际结果
# 字典格式:直接获取数据
# reality_res= jsonpath.jsonpath(result1, "$.msg")
# 字符串格式:先通过.loads()进行转换
dict_data = json.loads(result2)
reality_res = jsonpath.jsonpath(dict_data, "$.msg")
# 期望结果
desire_res = "登录成功"
# 断言:期望结果 == 实际结果
# assert desire_res == reality_res # 是一个列表需要通过下标获取具体的值
assert desire_res == reality_res[0]
print(reality_res)

接口关联 重要(上一个接口的响应数据作为下一个请求数据)

接口关联是在进行接口测试时,将一个接口的返回结果中的某些数据提取出来,然后作为后续接口请求的参数或者验证的依据。通过接口关联,可以实现接口间的数据传递和依赖关系的建立
接口关联通常分为两种类型:请求关联和响应关联

1. 请求关联:

提取关键参数:在一个接口的请求中,某些参数的值是由之前接口的响应结果提供的。需要提取出这些关键参数,并将其作为后续接口的请求参数。

例如,一个接口的请求中需要使用到某个用户的登录令牌(token),可以通过在登录接口的响应结果中提取出令牌(token),然后在后续接口的请求中使用

2. 响应关联:

验证关键数据:在一个接口的响应结果中,某些数据是需要验证的,可以将这些数据提取出来,并进行断言或者其他验证操作。

例如,一个接口的响应结果中包含了某个订单的状态信息,可以将该状态信息提取出来,然后进行断言,验证订单是否处于正确的状态

1. 首先登录成功--提取token

2. 通过用户去进行加入购物车。--- token值取进行指定

在线美化json地址:JSON在线解析及格式化验证 - JSON.cn

案例:通过登录的用户把登录的用户加入购物车

                

import requests
import jsonpath
# 案例一:登录接口
url = "http://shop-xo.hctestedu.com/index.php?s=/api/user/login"
public_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hami", "pwd": "123456", "type": "username"}
res = requests.post(url=url, params=public_data, data=data)
# ----------------------------------------
# 获取响应数据
result = res.json()
print(f"响应结果是:{result}")
# 期望结果
desire_res = "登录成功"
# 实际结果
reality_res = jsonpath.jsonpath(result, "$.msg")
# 断言:期望结果 == 实际结果
# assert desire_res == reality_res # 是一个列表需要通过下标获取具体的值
token = jsonpath.jsonpath(result, "$.data.token")
print(f"获取到的token值为:{token}")
assert desire_res == reality_res[0]
# 案例二:加入购物车
url = "http://shop-xo.hctestedu.com/index.php?s=/api/cart/save"
# public_data = {"application": "app", "application_client_type": "weixin", "token":
"8ae1ce79ed621a991a5e53ba9f96bfd3"}
public_data = {"application": "app", "application_client_type": "weixin", "token": token}
data = {
"goods_id": "11",
"spec": [
{
"type": "尺寸",
"value": "M"
}
],
"stock": "10"
} r
es = requests.post(url=url, params=public_data, data=data)
print(f"请求的url是:{res.url}")
# 获取响应数据
result = res.json()
print(f"响应结果是:{result}")
# 期望结果
desire_res = "加入成功"
# 实际结果
reality_res = jsonpath.jsonpath(result, "$.msg")
assert desire_res == reality_res[0]

对称加密与非对称加密

        

  我们使用加密目的是提高数据的安全性

        提高安全性的方法如下:     

  1. 在对应的协议加认证证书: http请求 --- https请求 (花钱去买一个安全)
  2. 通过一些常用的算法去进行解决: MDH\ SHA\ 编码:BASE64
  3. 通过对应加密方式去进行加密:对称加密 、非对称加密

               

                对称加密:

在对称加密算法中,加密和解密使用的是同一把钥匙,即:使用相同的密匙对                 同一密码进行加密和解密

               加密过程如下:

                加密:原文 + 密匙 = 密文

                解密:密文 - 密匙 = 原文

                对称加密代码如下:

                



"""
对称加密:加密和解密使用的是同一把钥匙,即:使用相同的密匙对同一密码进行加密和解密。
常用的加密方法:DES、3DES、AES...(AES算法是目前最常用的对称加密算法)
"""
import base64
from Crypto.Cipher import AES

class EncryptDate:
    # 构造方法
    def __init__(self, key):
        #  类属性
        self.key = key.encode("utf-8")  # 初始化密钥
        self.length = AES.block_size  # 初始化数据块大小 :16位
        self.aes = AES.new(self.key, AES.MODE_ECB)  # 初始化AES,ECB模式的实例
        # 截断函数,去除填充的字符
        self.unpad = lambda date: date[0:-ord(date[-1])]

    # 缺几位数据就补齐多少位数据:16的倍数
    def pad(self, text):  # text == tony
        """
        #填充函数,使被加密数据的字节码长度是block_size的整数倍
        """
        count = len(text.encode('utf-8'))  # count = 4
        add = self.length - (count % self.length)   # 求它们相差的位数
        # add = 16- (4%16)  === 16 - 4 == 12
        entext = text + (chr(add) * add)
        #  entext = “tony” + (chr(add) * 12  )  === entext == tony
        # print("entext的数据是:",entext)
        return entext

    # 加密函数
    def encrypt(self, encrData):  # 加密函数   encrData == tony (16位)
        res = self.aes.encrypt(self.pad(encrData).encode("utf8"))  # self.aes.encrypt(tony)
        msg = str(base64.b64encode(res), encoding="utf8")
        return msg

    # 解密函数
    def decrypt(self, decrData):  # 解密函数   XbXHJrNLwoTVcyfqM9eTgQ==
        # 从base64编码转回来
        res = base64.decodebytes(decrData.encode("utf8"))
        # 将数据进行对应的解密:XbXHJrNLwoTVcyfqM9eTgQ==
        msg = self.aes.decrypt(res).decode("utf8")
        # print("msg的值:",msg)
        # 把转回来的数据后面的字符去掉。
        return self.unpad(msg)

def fun1():
#     通过方法把这个接口请求通
     pass



if __name__ == '__main__':
    #  加密 :会补位
    key = "1234567812345678"  # key 密码
    data = "tony"  # 数据
    eg = EncryptDate(key)  # 这里密钥的长度必须是16的倍数,并且设置对应的【模式】
    res = eg.encrypt(str(data))
    print(f"加密后的数据为:{res}")


    #  解密 : 把后面的数据进行去除
    key = "1234567812345678"  # key 密码
    data = "XbXHJrNLwoTVcyfqM9eTgQ=="  # 数据
    eg = EncryptDate(key)  # 这里密钥的长度必须是16的倍数
    res = eg.decrypt(str(data))
    print(f"解密后的数据为:{res}")

                

                

                非对称加密:

        明白了对称加密后,我们来了解一下什么是非对称加密。我们知道,对称加密是使用的同一把密匙进行加密和解密。那么,非对称加密自然是使用 不同的密钥进行加密和解密 啦。

        非对称加密有两个钥匙,及公钥(Public Key)和私钥(Private Key)。公钥和私钥是成对的存在,如果对 原文 使用 公钥加密 ,则只能使用 对应的私钥 才能 解密 ;因为加密和解密使用的不是同一把密钥,所以这种算法称之为非对称加密算法。

非对称加密算法的密匙是通过一系列算法获取到的一长串随机数,通常随机数的长度越长,加密信息越安全。通过私钥经过一系列算法是可以推导出公钥的,也就是说,公钥是基于私钥而存在的。但是无法通过公钥反向推倒出私钥,这个过程是单向的

代码如下

        

# -*- coding: utf-8 -*-
import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher

# 注意开头
# PKCS1是BEGIN RSA PUBLIC KEY
# PKCS8是BEGIN PUBLIC KEY

"""
PKCS8 案例

"""
# 公钥
pub_str1 = '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgFAOoAvLNvQv8BNGQq7B
m8ifMIUaYnFIC2Vu3ahW98zu/0Bg2GFAiIShOlNZcP8dGVLX6J4+p3k6pFRhloWJ
nviJUVU1xdZGjnk6snARB2V+8u73o5HQqn7ISgipjIb8pQc9wCZNBBT5eOB83K44
5Md0slkgz05jQ9Cj4UcIHUWquwGNQYo3zy9DOqDJaWimu46O1HnZAWrADsBfURPB
p9cqqmnxYMejqkBbj9JWhw+3YLpB9sLMQib0p7MEGA8GrpG+cXGYxdI0f0ZfJqEt
TpuJHNdSZwN7oZiBhJlL+tHOIRcq2dFCKUMYgrW9XK8cJVJVYxU7R1e2ZURXSmP3
yQIDAQAB
-----END PUBLIC KEY-----'''

# 私钥
priv_str1 = '''-----BEGIN RSA PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCAUA6gC8s29C/w
E0ZCrsGbyJ8whRpicUgLZW7dqFb3zO7/QGDYYUCIhKE6U1lw/x0ZUtfonj6neTqk
VGGWhYme+IlRVTXF1kaOeTqycBEHZX7y7vejkdCqfshKCKmMhvylBz3AJk0EFPl4
4Hzcrjjkx3SyWSDPTmND0KPhRwgdRaq7AY1BijfPL0M6oMlpaKa7jo7UedkBasAO
wF9RE8Gn1yqqafFgx6OqQFuP0laHD7dgukH2wsxCJvSnswQYDwaukb5xcZjF0jR/
Rl8moS1Om4kc11JnA3uhmIGEmUv60c4hFyrZ0UIpQxiCtb1crxwlUlVjFTtHV7Zl
RFdKY/fJAgMBAAECggEALex5T47pDKIZBjPf0b36TWdgkl0RNGqW/n0vUOYPOmF+
qJzCDK/CCRpvGhD60hZ8s7OS0w7QHeClvGr3AoiI2PzbKOD2ffhTCGsbNwIlFiCd
bxVYTJLDvEHkLZssE7+8bNRKpZsPtYZMQ5cVGWbBtiAtBCgiNhA4Nu1VuitSHCdw
cpHrFCA7ESDmfmRGe7QAnTEkC2nUoM/9xPIBV4B1Lz3/KJuY+zJZWXkw1m64rC55
9cPILlc9zTrKYw0JSyC0PGXQSOZZ71TyEicsptVLIM2NT2ppdyu57i3IcVoFXyV6
XVoEWEFOXSppxkWXVXlYfJRT/rb1bEjzSCBWYKYGgQKBgQDLzcF1S/CMIlAW6LDY
vO0uoPOuMZE3yUUMASKrF2M0IuTZxO2Z/DSwwr3bt7X/r32sDceiVGAAj735VToh
ERhHOtgbP1s4S/rytHHMpAfEKciCcC8eNHvO4Q/N4W94B0uaUufamWRsgQog1F5F
12ymeuas0HApHTtEdohw1kR9uwKBgQChLMm5PyskU4ID0Jjse6XEwE4HcNCH9Qp6
MtBGznNLsGS2dLw8meKz6Q28ytgSGHPxFYEjzVmVKkiXzz95o6r3tn8so7IcfB+J
T55zn5DVK4o6ZYAeLWjBEzjTbbOIloFiOYgBHy9LXvV8kCN0bmBXvX1KEU2J6/Zh
rkIHRbZGSwKBgE0f+0MJTumpHofc3PfYXyWTMURNa7ghyahmUZlPi3IydkpW9Nee
Es6Fk9WvKwesgLF4sYCjz4TG4MyXTR0wW/CwuxFso3elgT0RvjMELBA3A7MhAyO6
FtROZW2zDzzr/ddT4nveKpvJJW0REO/7OxmxTtQ9OQTGFCSveqjA3UB7AoGBAJ4j
QbGehwfXX6O6kbDGCPmo7WZjjFc5WBRZsv0mJv3GjqpukxqqqkJ3keEA7Uuj7m5G
+TRVkWXH3P4GfHMu4Nq3lsQHwQQtzQt+sSslDof5dmChojj5uORnpcPcyOBlO4FS
jVz8afz7qMWU7xSYD7NG2p1HqNqASHfC8EoOXi9NAoGAZT5ezE1bTpIo40wArVJG
TA4R59m9RugGIFQl2Tpqw9ACUTjVNBkNtCpLEYV9Fznwy1PxE2OW5zGgpwWPm63D
D4tH1xShy5jOm7MIF7afrYgPbIYXyIdFtXY7sJuLETD2sYFBHG5ocZ4Pto/ELV7g
iK3ec+5UKwA/TN7l7Q7NE9A=
-----END RSA PRIVATE KEY-----
'''


class Rsa:
    # 自动调用我们构造方法加载对应的公钥和私钥
    def __init__(self):
        # 加载公钥
        self.pub_key = RSA.importKey(pub_str1)
        # 加载私钥
        self.pri_Key = RSA.importKey(priv_str1)

    # rsa加密,返回加密结果
    def encrypt(self, text):
        # 1. 创建一个加密器对象 cipher,使用 self.pub_key 作为公钥
        cipher = PKCS1_cipher.new(self.pub_key)
        # 2. 加密:将text.encode("utf-8)" 转为b64编码
        rsa_text = base64.b64encode(cipher.encrypt(text.encode("utf-8)")))
        # 3. 解码为字符串
        text = rsa_text.decode("utf8")
        return text

    # rsa解密 返回解密结果
    def decrypt(self, text):
        # 1. 创建一个加密器对象 cipher,使用self.pri_Key作为公钥
        cipher = PKCS1_cipher.new(self.pri_Key)
        # 2. 解密:将密文数据 text 转换为 UTF-8 编码的字节序列,
        # 然后使用cipher对象调用decrypt()方法进行解密。
        # 解密前,还需要对密文进行 Base64 解码,得到原始的加密结果。
        # 第二个参数 0 表示不使用任何的填充方式
        rsa_text = cipher.decrypt(base64.b64decode(text.encode("utf8")), 0)
        # 解码为字符串
        text = rsa_text.decode("utf8")
        return text


if __name__ == "__main__":
    # 1. 实例化对象
    rsaer = Rsa()
    # 2. 进行加密处理
    info = rsaer.encrypt('哈米')
    print('加密:', info)
    # 3. 进行解密处理
    print('解密:', rsaer.decrypt(info))


     

                

                

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值