场景
压测评论、点赞等带有用户登录信息的接口时, 请求参数中需要带token,而token是登录后接口返回的,且一段时间内不过期,所以只登录一次,获取到的token在有效期内可一直使用
思路
1.app连接代理charles,app登录,charles抓取接口请求数据,转换为json格式,如下图
2.on_start()登录一次获取token,一遍其它接口使用
3.sign根据定义的规则生成,后文示例具体代码
4.timestamp也是实时变化的,后文示例具体代码
5.密码可能使用md5或其他方式加密,后文示例具体代码
示例脚本
from locust import HttpUser, TaskSet, task
import subprocess
import json # abc
# 性能测试任务类 TaskSet.
class UserBehavior(TaskSet):
# 登录截取token
def doLogin(self):
# 只写路径即可
login_url = "/login/accountLogin"
# 由于本例中的timestamp和每个接口请求的sign一段时间内是不变的,所以直接使用抓取的接口数据
# 密码可直接从接口中抓取已加密过的数据,也可在脚本中根据规则转换
login_params = {
"_sign": "833e83c223faf3ef446573d05618d150",
"_timestamp": "1626312457295",
"_v": "1.0.0",
"os": "android",
"password": "yourpassword",
"terminal": "1",
"username": "yourname",
"uuid": "youruuid"
}
response = self.client.post(url=login_url, params=login_params)
ret = json.loads(response.content)["results"]["ret"]
if ret == 200:
print(u"登录成功")
print(json.dumps(ret, ensure_ascii=False))
else:
print(u"登录失败")
print(ret)
# 此处获取的token,可在后面的函数中使用
self.token = json.loads(response.content)["results"]["data"]["access_token"]
if self.token != 0:
print(self.token)
return self.token
# 在进行压测前,执行一次
def on_start(self):
print("--------------登录获取token--------------")
self.doLogin()
# 任务,数字表示权重,数字越大,执行的概率越高
@task(1)
def getTagVals(self):
global token
u"""
request_url:请求路径
request_params:请求头参数
request_json:请求json参数
"""
request_url = "/video/commitComment"
request_params = {
"_sign": "833e83c223faf3ef446573d05618d150",
"_timestamp": "1626312457295",
"_v": "1.0.0",
"content": "2222",
"key": "9db6b3345fbd41c7bd42e239e655fce7",
"os": "android",
"terminal": "1",
# 调用获取的token
"token": self.token,
"uuid": "youruuid"
}
response = self.client.post(
url=request_url,
params=request_params,
)
# 这里可以编写自己需要校验的返回内容
content = json.loads(response.content)["results"]["ret"]
if content == 200:
print(u"评论成功")
print(json.dumps(content, ensure_ascii=False))
else:
print(u"评论失败")
print(content)
# 性能测试配置
class MobileUserLocust(HttpUser):
u"""
min_wait :用户执行任务之间等待时间的下界,单位:毫秒。
max_wait :用户执行任务之间等待时间的上界,单位:毫秒。
"""
# weight = 3
tasks = [UserBehavior]
host = "https://*****.cn"
min_wait = 3000
max_wait = 6000
if __name__ == "__main__":
subprocess.Popen("locust -f main_pt.py", shell=True)
sign、timestamp、md5加密实例代码
获取timestamp、生成sign
import time
import urllib.parse
import hashlib
#获取当前的时间戳
stamp = time.time()
print(stamp)
#转换为int类型的13位时间戳
timestam = int(round(stamp*1000))
print(timestam)
time_new = str(timestam)
print(type(time_new))
data ={
"_v": "1.0.0",
"os": "android",
"password": "youpassword",
"terminal": 1,
"username": "yourname",
"uuid": "uuid"
}
# 将键值按照首字母升序排列
data_order = sorted(data.items(),key=lambda x:x[0],reverse=False)
# 将列表转化为字典
datadic = dict(data_order)
print(datadic)
# 将key=value键值对进行url编码
datacode = urllib.parse.urlencode(datadic)
# 替换url中的“=”“&”为“+”
datastr = datacode.replace("=","+").replace("&","+")
datasec = "defination" + datastr + "_timestamp" + time_new + "defination"
print(datasec)
#创建md5对象,进行md5加密
m = hashlib.md5()
m= hashlib.md5(datasec.encode())
data_md5 = m.hexdigest()
#将小写字母切换为大写字母
sign=data_md5.upper()
print(sign)
参数中直接转换明文密码为md5加密后的字符串
def login(self):
data = {
"account": '*******',
"password": hashlib.md5("明文密码").hexdigest()
}
response = self.client.post('/path',data=data)
content = json.loads(response.content)
result = response.json()["result"]
if result == 0:
userId = content['content']['id']
print (userId)
else:
print (u"登录失败")