Python + requests + unittest 接口自动化
标签: Python + requests + unittest 接口自动化 博客 51CTO博客
2023-07-14 18:24:15 65浏览
一、技术选型
Python + Requests 借助 unittest 单元测试框架、HTMLTest Runner 生成测试报告,logging模块生成日志;
二、环境搭建
- 下载 python 并配置环境变量;
- 安装 pip;
- 安装 requests
pip3 install requests
- 安装 jdk 并配置环境变量;
- 安装其他需要引用的模块
pip install unittest
pip install html-testRunner
三、requests 基本使用
import requests
class Test:
@classmethod
def SimulateGet(cls, url, params):
res = requests.get(url, params)
print(str(res.status_code), res.text)
@classmethod
def SimulatePost(cls, url, params):
res = requests.post(url, json=params)
print(str(res.status_code), res.text)
if __name__ == '__main__':
url = "https://api-v2.xdclass.net/api/funny/v1/get_funny"
params = None
Test.SimulateGet(url=url, params=params)
url = "https://api-v2.xdclass.net/api/account/v1/login"
params = {}
params["identifier"] = "13113777555"
params["credential"] = "1234567890"
Test.SimulatePost(url=url, params=params)
注意:
1,post 接口在接收 params 参数时,有 json 和 data 两种格式,当 header 中的 ["Content-Type"] == "application/json" 时,使用 json,当 ["Content-Type"] 非 "application/json" 时,使用 data;
2,res.status_code 为响应状态码,res.text 为响应体内容;
四、Token & Cookies 处理和使用
提取接口返回的 token 值:
class RequestsUtil:
@classmethod
def SimulateLogin(cls):
url = "https://api.xdclass.net/pub/api/v1/web/web_login"
params = {}
params["phone"] = "13113777555"
params["pwd"] = "1234567890"
headers = {}
headers["Content-Type"] = "application/x-www-form-urlencoded"
res = requests.post(url=url, data=params, headers=headers, verify=False)
print(res.status_code)
print(res.text)
res = cls.__toJsonObject(res.text)
print(res["data"]["token"])
token = res["data"]["token"]
return token
token 的使用,参见第 “十章节,1,需要登录态的接口”;
返回 cook 值:
class RequestsUtil:
@classmethod
def SimulateLogin(cls):
url = "https://api-v2.xdclass.net/api/account/v1/login"
params = {}
params["identifier"] = "13113777555"
params["credential"] = "1234567890"
headers = {}
headers["Content-Type"] = "application/json"
res = requests.post(url=url, json=params, headers=headers)
return res.cookies
当其他接口需要 cookie 时:
五、接口封装
使用 getattr 方法,将 get 和 post 请求封装;
import json
import requests
class Test:
@classmethod
def apiUrl(cls, methodType, url, params, headers):
# 判断url是否为string
if not isinstance(url, str):
raise Exception("param url must be string")
if methodType.lower() not in ["get", "post"]:
raise Exception("only support get or post option")
# getattr(requests, methodType.lower()) 相当于requests.get/.post
if methodType == "post":
if headers["Content-Type"] == "application/json":
res = getattr(requests, methodType.lower())(url, json=params, headers=headers)
else:
res = getattr(requests, methodType.lower())(url, data=params, headers=headers)
else:
res = getattr(requests, methodType.lower())(url, params=params, headers=headers)
return res.status_code, cls.__toJsonObject(res.text)
@classmethod
def __toJsonObject(cls, s):
jsonObj = s
# 将str转换为字典类型
try:
jsonObj = json.loads(s)
except Exception as e:
print(e)
return jsonObj
if __name__ == '__main__':
# application/json 格式的 post 接口
methodtype = "post"
url = "https://api-v2.xdclass.net/api/account/v1/login"
params = {}
params["identifier"] = "13113777555"
params["credential"] = "1234567890"
headers = {}
headers["Content-Type"] = "application/json"
status, jsonObj = Test.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
print(status, jsonObj)
# get 接口
methodtype = "get"
url = "https://api-v2.xdclass.net/api/funny/v1/get_funny"
params = None
headers = None
status, jsonObj = Test.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
print(status, jsonObj)
# 非application/json 格式的 post 接口
methodtype = "post"
# 提示以下Url涉及敏感信息,固部分打码处理
url = "https://***.com/j/collect?v=1&_v=j100&a=36020002&t=pageview&_s=1&dl=https%3A%2F%2Fwww.cnblogs.com%2F&dr=https%3A%2F%2Fzzk.cnblogs.com%2F&ul=zh-cn&de=UTF-8&dt=%E5%8D%9A%E5%AE%A2%E5%9B%AD%20-%20%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84%E7%BD%91%E4%B8%8A%E5%AE%B6%E5%9B%AD&sd=24-bit&sr=1536x864&vp=1519x308&je=0&_u=QACAAUABAAAAACAAI~&jid=772208080&gjid=1713900691&cid=420515007.1646791376&tid=UA-476124-1&_gid=446978872.1685770072&_r=1>m=457e35v0&jsscut=1&z=1817878671"
params = None
headers = {}
headers["Content-Type"] = "text/plain"
status, jsonObj = Test.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
print(status, jsonObj)
六、测试数据管理
testdata.xml
<?xml version="1.0" encoding="UTF-8"?>
<datas>
<testLoginData>
<methodtype>post</methodtype>
<url>https://api-v2.xdclass.net/api/account/v1/login</url>
<params>{"identifier":"13113777555","credential":"1234567890"}</params>
<headers>{"Content-Type":"application/json"}</headers>
</testLoginData>
</datas>
psetting.py
import os
ROOT_DIR = os.path.dirname(__file__)
DataProvider.py
from xml.dom.minidom import parse
# 直接引用 psetting 会报错
from src import psetting
class DataProvider(object):
def __init__(self, filename):
self.filename = filename
self.doc = parse(filename)
self.root = self.doc.documentElement
print(self.filename)
def getValue(self, firstTag, secondTag):
'''
获取xml文件中对应节点的值
@param firstTag:第一个节点的名称
@param secondTag:第二个节点的名称
@return: 返回的是第二个节点的值
'''
d = self.root.getElementsByTagName(firstTag) # return NodeList
if(len(d) > 0):
n = d[0].getElementsByTagName(secondTag) # return NodeList
if(len(n) > 0):
o = n[0]
if(o.hasChildNodes): # Element 包含 Test Node
return o.childNodes[0].nodeValue
return None
if '__main__' == __name__:
parseXml = DataProvider(psetting.ROOT_DIR + "/TestData/testdata.xml")
methodtype = parseXml.getValue("testLoginData", "methodtype")
url = parseXml.getValue("testLoginData", "url")
params = parseXml.getValue("testLoginData", "params")
headers = parseXml.getValue("testLoginData", "headers")
七、使用 unittest
RequestsUtil.py
加入 login 方法,返回 cookie
import json
import requests
class RequestsUtil:
@classmethod
def SimulateLogin(cls):
url = "https://api-v2.xdclass.net/api/account/v1/login"
params = {}
params["identifier"] = "13113777555"
params["credential"] = "1234567890"
headers = {}
headers["Content-Type"] = "application/json"
res = requests.post(url=url, json=params, headers=headers)
return res.cookies
@classmethod
def apiUrl(cls, methodType, url, params, headers, cookies):
# 判断url是否为string
if not isinstance(url, str):
raise Exception("param url must be string")
if methodType.lower() not in ["get", "post"]:
raise Exception("only support get or post option")
# getattr(requests, methodType.lower()) 相当于requests.get/.post
if methodType == "post":
if headers["Content-Type"] == "application/json":
res = getattr(requests, methodType.lower())(url, json=params, headers=headers,cookies=cookies)
else:
res = getattr(requests, methodType.lower())(url, data=params, headers=headers,cookies=cookies)
else:
res = getattr(requests, methodType.lower())(url, params=params, headers=headers,cookies=cookies)
return res.status_code, cls.__toJsonObject(res.text)
@classmethod
def __toJsonObject(cls, s):
jsonObj = s
# 将str转换为字典类型
try:
jsonObj = json.loads(s)
except Exception as e:
print(e)
return jsonObj
testdata.xml
<?xml version="1.0" encoding="UTF-8"?>
<datas>
<testGetFunny>
<methodtype>get</methodtype>
<url>https://api-v2.xdclass.net/api/funny/v1/get_funny</url>
<params>None</params>
<headers>None</headers>
</testGetFunny>
<testDetail>
<methodtype>get</methodtype>
<url>https://api-v2.xdclass.net/api/account/v1/detail</url>
<params>None</params>
<headers>{"token":"dcloud-clienteyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4ZGNsYXNzIiwiaGVhZF9pbWciOiJodHRwczovL3RoaXJkd3gucWxvZ28uY24vbW1vcGVuL3ZpXzMyL1EwajRUd0dUZlRLcjNua3Q1YTdKR21SNERWdzkxQ0cwUDRMQzBpYmttQTl6a09WUldhS2h3eGFZOHRFa0hQSHAzeUpuaWJqdVdkVFhRc3kyZUN2NzdIOEEvMTMyIiwiYWNjb3VudF9pZCI6NjgwODMzNCwidXNlcm5hbWUiOiJNcnN-44COQXBwbGXjgI8iLCJyb2xlIjoiQ09NTU9OIiwibWVkYWwiOiIiLCJpYXQiOjE2ODU4NTg0MTUsImV4cCI6MTY4NjQ2MzIxNX0.FxskUd9PqxJiYoZHOaiB-1BZ-y4e57v2YaZM2erXnK4"}</headers>
</testDetail>
</datas>
创建 testcase:TestGetUse.py
import unittest
from CommonFunction import RequestsUtil as requestUtil
from CommonFunction import DataProvider as parseXML
import psetting
class TestGetUser(unittest.TestCase):
# 获取cookie
def setUp(self):
print("setup")
self.cook = requestUtil.RequestsUtil.SimulateLogin()
def test_getFunny(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/testdata.xml")
methodtype = data.getValue("testGetFunny", "methodtype")
url = data.getValue("testGetFunny", "url")
params = data.getValue("testGetFunny", "params")
headers = eval(data.getValue("testGetFunny", "headers"))
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers,
cookies=self.cook)
if (status == 200):
self.assertIsNotNone(res["data"], "返回结果不应为空")
self.assertEqual(0, res["code"], "业务状态码应为0")
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
def test_detail(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/testdata.xml")
methodtype = data.getValue("testDetail", "methodtype")
url = data.getValue("testDetail", "url")
params = data.getValue("ttestDetail", "params")
headers = eval(data.getValue("testDetail", "headers"))
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers,
cookies=self.cook)
if (status == 200):
self.assertIsNotNone(res["data"], "返回结果不应为空")
self.assertEqual(0, res["code"], "业务状态码应为0")
self.assertEqual(6808334, res["data"]["accountId"])
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
if __name__ == "__main__":
unittest.main()
注意从 xml 文件中读取 header 时,返回的是 json 字符串,需利用 eval 函数将字符串转换为字典;
若要仅执行一次 setup,则使用装饰器:
@classmethod
def setUpClass(cls):
super(TestGetUser, cls).setUpClass()
八、日志记录
logging.cofig
[loggers]
keys=root,simpleRotateFileLogger
[handlers]
keys=consoleHandler,simpleHandler
[formatters]
keys=simpleFormatter
[logger_root]
# level DEBUG, INFO, WARNING, ERROR, CRITICAL or NOTSET
level=DEBUG
handlers=consoleHandler
[logger_simpleRotateFileLogger]
level=DEBUG
handlers=consoleHandler,simpleHandler
qualname=simpleRotateFileLogger
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[handler_simpleHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=simpleFormatter
# def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)
args=("apiTest.log","a",6*1024*1024,5,"UTF-8")
[formatter_simpleFormatter]
format=%(asctime)s %(levelname)s %(module)s %(funcName)s %(lineno)d %(message)s
datefmt=
class=logging.Formatter
LoggerHelper
import logging.config as lc
import logging
import psetting
class LoggerHelper(object):
'''日志帮助类,记录日志'''
Logger = None
@classmethod
def getLogger(cls):
if cls.Logger is None:
lc.fileConfig(psetting.ROOT_DIR + "/config/logging.config")
cls.Logger = logging.getLogger("simpleRotateFileLogger")
return cls.Logger
import unittest
from CommonFunction import RequestsUtil as requestUtil
from CommonFunction import DataProvider as parseXML
import psetting
from CommonFunction.LoggerHelper import LoggerHelper
class TestGetUser(unittest.TestCase):
# 获取cookie
def setUp(self):
print("setup")
self.log = LoggerHelper().getLogger()
self.cook = requestUtil.RequestsUtil.SimulateLogin()
def test_getFunny(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/testdata.xml")
methodtype = data.getValue("testGetFunny", "methodtype")
url = data.getValue("testGetFunny", "url")
self.log.info("test_getFunny url %s" % url)
params = data.getValue("testGetFunny", "params")
headers = eval(data.getValue("testGetFunny", "headers"))
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers,
cookies=self.cook)
self.log.info("return result status %s res %s" % (status, res))
if (status == 200):
self.assertIsNotNone(res["data"], "返回结果不应为空")
self.assertEqual(0, res["code"], "业务状态码应为0")
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
def test_detail(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/testdata.xml")
methodtype = data.getValue("testDetail", "methodtype")
url = data.getValue("testDetail", "url")
self.log.info("test_detail url %s" % url)
params = data.getValue("ttestDetail", "params")
headers = eval(data.getValue("testDetail", "headers"))
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers,
cookies=self.cook)
self.log.info("return result status %s res %s" % (status, res))
if (status == 200):
self.assertIsNotNone(res["data"], "返回结果不应为空")
self.assertEqual(0, res["code"], "业务状态码应为0")
self.assertEqual(6808334, res["data"]["accountId"])
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
if __name__ == "__main__":
unittest.main()
运行后,自动生成日志文件
九、测试报告
使用 unittest 框架下的 testsuite 套件,TestSuite.py
import unittest
import psetting
from HtmlTestRunner.runner import HTMLTestRunner
class TestSuite(object):
'''
classdocs
'''
if __name__ == '__main__':
suite = unittest.TestLoader().discover(start_dir=psetting.ROOT_DIR + "/TestCase", pattern="Test*.py")
result = HTMLTestRunner(output=psetting.ROOT_DIR+'/reports',report_title=r"接口测试自动化报告", report_name=r"测试报告").run(test=suite)
if result.wasSuccessful():
print("接口测试执行完成")
TestGetUser.py
if __name__ == "__main__":
unittest.main(testRunner=HTMLTestRunner(output=psetting.ROOT_DIR + '/reports'))
十、不同用例场景
1,需要登录态的接口
用户个人信息
请求方式:get
路径:/pub/api/v1/web/user_info
请求头:
请求头 |
解释 |
token |
登录接口返回token |
请求参数:无
那么我们在测试用例执行前,最先执行登录接口,获取到token:
RequestsUtil.py封装函数:
import json
import requests
import jsonpath
import logging
logging.captureWarnings(True)
class RequestsUtil:
@classmethod
def SimulateLogin(cls):
url = "https://api.xdclass.net/pub/api/v1/web/web_login"
params = {}
params["phone"] = "13113777555"
params["pwd"] = "1234567890"
headers = {}
headers["Content-Type"] = "application/x-www-form-urlencoded"
res = requests.post(url=url, data=params, headers=headers, verify=False)
print(res.status_code)
print(res.text)
res = cls.__toJsonObject(res.text)
print(res["data"]["token"])
token = res["data"]["token"]
return token
@classmethod
def apiUrl(cls, methodType, url, params, headers, cookies):
# 判断url是否为string
if not isinstance(url, str):
raise Exception("param url must be string")
if methodType.lower() not in ["get", "post"]:
raise Exception("only support get or post option")
# getattr(requests, methodType.lower()) 相当于requests.get/.post
if methodType == "post":
if headers["Content-Type"] == "application/json":
res = getattr(requests, methodType.lower())(url, json=params, headers=headers, cookies=cookies)
else:
res = getattr(requests, methodType.lower())(url, data=params, headers=headers, cookies=cookies)
else:
res = getattr(requests, methodType.lower())(url, params=params, headers=headers, cookies=cookies)
return res.status_code, cls.__toJsonObject(res.text)
@classmethod
def __toJsonObject(cls, s):
jsonObj = s
# 将str转换为字典类型
try:
jsonObj = json.loads(s)
except Exception as e:
print(e)
return jsonObj
if __name__ == "__main__":
RequestsUtil.SimulateLogin()
testdata.xml
<?xml version="1.0" encoding="UTF-8"?>
<datas>
<testUserInfo>
<methodtype>get</methodtype>
<url>https://api.xdclass.net/pub/api/v1/web/user_info</url>
<params>None</params>
<headers>{}</headers>
</testUserInfo>
</datas>
TestUserInfo.py
import unittest
from CommonFunction import RequestsUtil as requestUtil
from CommonFunction import DataProvider as parseXML
import psetting
from CommonFunction.LoggerHelper import LoggerHelper
from HtmlTestRunner.runner import HTMLTestRunner
class TestUserInfo(unittest.TestCase):
# 获取token
def setUp(self):
print("setup")
self.log = LoggerHelper().getLogger()
self.token = requestUtil.RequestsUtil.SimulateLogin()
def test_userIner(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/testdata.xml")
methodtype = data.getValue("testUserInfo", "methodtype")
url = data.getValue("testUserInfo", "url")
self.log.info("test_UserInfo url %s" % url)
params = eval(data.getValue("testUserInfo", "params"))
headers = eval(data.getValue("testUserInfo", "headers"))
headers["token"] = self.token
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
self.log.info("return result status %s res %s" % (status, res))
if (status == 200):
self.assertIsNotNone(res["data"], "返回结果不应为空")
self.assertEqual(0, res["code"], "业务状态码应为0")
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
if __name__ == "__main__":
unittest.main(testRunner=HTMLTestRunner(output=psetting.ROOT_DIR + '/reports'))
2,Get 接口
在上例中已经覆盖;
3,Post json 类型接口
#-*- encoding:utf-8 -*-
import unittest
from CommonFunction import RequestsUtil as requestUtil
from CommonFunction import DataProvider as parseXML
import psetting
from CommonFunction.LoggerHelper import LoggerHelper
from HtmlTestRunner.runner import HTMLTestRunner
class TestUserFavorite(unittest.TestCase):
def setUp(self):
print("setup")
self.log = LoggerHelper().getLogger()
def test_userJsonPost(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/TestJsonPost.xml")
methodtype = data.getValue("testJsonPost", "methodtype")
url = data.getValue("testJsonPost", "url")
self.log.info("test_JsonPost url %s" % url)
params = eval(data.getValue("testJsonPost", "params"))
headers = eval(data.getValue("testJsonPost", "headers"))
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
self.log.info("return result status %s res %s" % (status, res))
if (status == 200):
self.assertEqual(0, res["code"], "业务状态码应为0")
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
if __name__ == "__main__":
unittest.main(testRunner=HTMLTestRunner(output=psetting.ROOT_DIR + '/reports'))
<?xml version="1.0" encoding="UTF-8"?>
<datas>
<testJsonPost>
<methodtype>post</methodtype>
<url>https://api-v2.xdclass.net/api/account/v1/login</url>
<params>{"identifier": "13113777555","credential":"1234567890"}</params>
<headers>{"Content-Type":"application/json"}</headers>
</testJsonPost>
</datas>
4,Post data 类型接口
#-*- encoding:utf-8 -*-
import unittest
from CommonFunction import RequestsUtil as requestUtil
from CommonFunction import DataProvider as parseXML
import psetting
from CommonFunction.LoggerHelper import LoggerHelper
from HtmlTestRunner.runner import HTMLTestRunner
class TestUserFavorite(unittest.TestCase):
# 获取token
def setUp(self):
print("setup")
self.log = LoggerHelper().getLogger()
self.token = requestUtil.RequestsUtil.SimulateLogin()
def test_userFavorite(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/TestUserFavorite.xml")
methodtype = data.getValue("testUserFavorite", "methodtype")
url = data.getValue("testUserFavorite", "url")
self.log.info("test_UserFavorite url %s" % url)
params = eval(data.getValue("testUserFavorite", "params"))
headers = eval(data.getValue("testUserFavorite", "headers"))
headers["token"] = self.token
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
self.log.info("return result status %s res %s" % (status, res))
if (status == 200):
self.assertEqual(0, res["code"], "业务状态码应为0")
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
if __name__ == "__main__":
unittest.main(testRunner=HTMLTestRunner(output=psetting.ROOT_DIR + '/reports'))
<?xml version="1.0" encoding="UTF-8"?>
<datas>
<testUserFavorite>
<methodtype>post</methodtype>
<url>https://api.xdclass.net/user/api/v1/favorite/save</url>
<params>{"video_id": "50"}</params>
<headers>{"Content-Type":"application/x-www-form-urlencoded"}</headers>
</testUserFavorite>
</datas>
5,异常场景入参
def test_userExecJsonPost(self):
data = parseXML.DataProvider(psetting.ROOT_DIR + "/TestData/TestJsonPost.xml")
methodtype = data.getValue("testExecJsonPost", "methodtype")
url = data.getValue("testExecJsonPost", "url")
self.log.info("test_ExecJsonPost url %s" % url)
params = eval(data.getValue("testExecJsonPost", "params"))
headers = eval(data.getValue("testExecJsonPost", "headers"))
status, res = requestUtil.RequestsUtil.apiUrl(methodType=methodtype, url=url, params=params, headers=headers)
self.log.info("return result status %s res %s" % (status, res))
if (status == 200):
self.assertEqual(1, res["code"], "业务状态码应为0")
self.assertIsNotNone(res, "返回结果不应为空")
self.assertEqual("账号不能为空!", res["msg"], "msg提示语不正确")
else:
self.assertEqual(200, status, "返回状态码应为200")
self.assertIsNotNone(res, "返回结果不应为空")
<?xml version="1.0" encoding="UTF-8"?>
<datas>
<testJsonPost>
<methodtype>post</methodtype>
<url>https://api-v2.xdclass.net/api/account/v1/login</url>
<params>{"identifier": "13113777555","credential":"1234567890"}</params>
<headers>{"Content-Type":"application/json"}</headers>
</testJsonPost>
<testExecJsonPost>
<methodtype>post</methodtype>
<url>https://api-v2.xdclass.net/api/account/v1/login</url>
<params>{"identifier": "","credential":"1234567890"}</params>
<headers>{"Content-Type":"application/json"}</headers>
</testExecJsonPost>
</datas
十一、整体代码的框架结构
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论
您可能感兴趣的博客