getattr和eval在Python接口测试中的应用

1、getattr官方说明

getattr() 函数用于返回一个对象属性值

  • object – 对象。
  • name – 字符串,对象属性。
  • default – 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError
def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass

2、getattr示例1,简单对象,只有属性值

class A:
    bar = 1
    
a = A()

2.1 获取属性bar值

# 方式1:通过类对象获取属性bar值
print(a.bar)

# 方式2: 通过getattr方法获取属性bar值
value = getattr(a, 'bar')
print(value)

运行结果:

1
1

2.2 属性bar2不存在

# 属性bar2不存在,为类A增加一个bar2属性,且值为3
d = getattr(a, 'bar2', 3)
print(d)

运行结果:

3

2.3 属性bar3不存在,没有默认值,将触发异常

# 属性bar3不存在, 没有默认值,触发异常
e = getattr(a, 'bar3')
print(e)

运行结果:

Traceback (most recent call last):
  File "E:\Coding\python-workspace\base_tec\my_getattr.py", line 34, in <module>
    e = getattr(a, 'bar3')
AttributeError: 'A' object has no attribute 'bar3'. Did you mean: 'bar'?

3、getattr示例2,常规对象,有方法

class B:
    def set(self, c, d):
        print(c + d)


b = B()

res1 = getattr(b, 'set')(c=1, d=2)
res2 = getattr(B(), 'set')(c=2, d=3)

data = {
    "c": 5,
    "d": 6
}

# 反射加解包,将参数值存储在字典中。此方式可以用于发送接口请求,将请求数据存储在一个字典中,调用post/get请求方法,效果等同于requests.get()、requests.post()
res3 = getattr(B(), 'set')(**data)

运行结果:

3
5
11

4、eval的用法

4.1 eval官方说明

将字符串str当做有效的表达式来求值并返回计算结果

4.2 字符串转换成算术表达式

a = '1+1'
print(eval(a))   # 2

4.3 字符串转换成列表

a = '[[1,2],[3,4],[5,6]]'
b = eval(a)
print(b)
print(type(b))

运行结果:

[[1, 2], [3, 4], [5, 6]]
<class 'list'>

4.4 字符串转换成元组

示例1:

a = '[1,2],[3,4],[5,6]'
b = eval(a)
print(b)
print(type(b))

运行结果:

([1, 2], [3, 4], [5, 6])
<class 'tuple'>

示例2:

a = '1,2,3,4,5,6'
b = eval(a)
print(b)
print(type(b))

运行结果:

(1, 2, 3, 4, 5, 6)
<class 'tuple'>

4.5 字符串转换成字典

a = "{'a': 1,'b': 2}"
b = eval(a)
print(b)
print(type(b))

运行结果:

{'a': 1, 'b': 2}
<class 'dict'>

4.6 字符串重复

result = eval("'+' * 5")
print(result) 

运行结果:

+++++

4.7 eval不能滥用于input

4.7.1 eval转换成input结果的简单示例

input_number = input("请输入一个加减乘除运算公式:")
print(eval(input_number))

运行结果:

请输入一个加减乘除运算公式:1+5
6

4.7.2 为什么不能滥用于input

因为在input时,用户直接通过os这个模块来调用system方法可以执行任何的终端命令,所以eval滥用于input会有安全隐患。

__import__('os').system('ls')

# 等价代码(上面代码等价于下面代码)

import os
os.system('终端命令')

5、getattr和eval在接口测试中的应用场景

5.1 apikey封装

import json
import logging
import allure
import jsonpath
import requests

# 工具类/关键字驱动类/基类
class ApiKey:
    # get请求的封装:因为params可能存在无值的情况,存放默认None
    @allure.step("发送get请求")
    def get(self, url, params=None, **kwargs):
        return requests.get(url=url, params=params, **kwargs)

    @allure.step("发送post请求")
    # post请求的封装:data也可能存在无值得情况,存放默认None
    def post(self, url, data=None, **kwargs):
        return requests.post(url=url, data=data, **kwargs)

    @allure.step("获取返回结果字典值")
    # 基于jsonpath获取数据的关键字:用于提取所需要的内容
    def get_text(self, data, key):
        # jsonpath获取数据的表达式:成功则返回list,失败则返回false
        # loads是将json格式的内容转换为字典的格式
        # jsonpath接收的是dict类型的数据
        dict_data = json.loads(data)
        value = jsonpath.jsonpath(dict_data, key)
        if isinstance(value, list):
            return value[0]
        else:
            return value

    @allure.step("断言实际结果等于预期结果")
    def my_assert(self, acutal, expect):
        try:
            assert acutal == expect
        except:
            return "断言失败"
        else:
            return "断言成功"

5.2 接口测试用例

ak = ApiKey()
# 为了简化例子步骤,将接口测试用例写成如下格式。实际上dict_data是从excel表格中读取到的测试用例。从excel对出来的都是字符串,因此使用eval方法将字符串转换成其他有效的数据类型。
dict_data = {
    'url': "http://shop-xo.hctestedu.com/index.php?s=api/user/login",
    'params': eval('{"application": "app",\n"application_client_type": "weixin"}'),
    'headers': eval('None'),
    'data': eval('{"accounts":"zzss","pwd":"123456","type": "username"}')
}
# 发起请求
# 反射+解包,等同于 requests.post()
res = getattr(ak, 'post')(**dict_data)
# 打印响应报文
print(res.text)

运行结果:

{"msg":"登录成功","code":0,"data":{"id":"70734","username":"zzss","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"189","locking_integral":"0","referrer":"0","add_time":"1646195490","add_time_text":"2022-03-02 12:31:30","mobile_security":"","email_security":"","user_name_view":"zz","is_mandatory_bind_mobile":0,"token":"f3e24ef665bad26785704838ccxba794"}}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Summer@123

不积跬步无以至千里,感谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值