api_keys
api_keys.py
'''
接口的关键字驱动类底层:
1. 核心还是基于requests来实现的。
2. 整体还是以模拟请求为主
3. 响应的获取与解析
接口关联解决手段只有两种:
1. 将关联数据写入文件之中:适合相对于业务复杂程度更高的接口测试。
2. 将关联数据作为全局变量:适合关联数据相对较少的接口测试。
'''
import json
import jsonpath
import requests
from class33_interface_auto.conf import set_conf
class Api:
# get请求:需要在方法中将常见的参数定义好
def do_get(self, path=None, params=None, headers=None, **kwargs):
# 获取url
url = self.set_url(path)
# 获取headers
headers = self.set_headers(headers)
return requests.get(url=url, headers=headers, params=params, **kwargs)
# post请求
def do_post(self, path=None, data=None, headers=None, json=1, **kwargs):
# 获取url
url = self.set_url(path)
# 获取headers
headers = self.set_headers(headers)
# 发送post请求
if json == 1:
response = requests.post(url=url, headers=headers, json=data, **kwargs)
else:
response = requests.post(url=url, headers=headers, data=data, **kwargs)
return response
# 拼接URL
def set_url(self, path):
url = set_conf.read_conf('SERVERS', 'TESTS')
if path:
url = url + path
return url
# 拼接headers
def set_headers(self, headers):
base_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/115.0.0.0 Safari/537.36"
}
if headers:
# 如果用户传入新的headers值,则拼接在原有的base_headers之后
base_headers.update(headers)
if set_conf.read_conf('HEADERS', 'access-token'):
print(1)
access_token = set_conf.read_conf('HEADERS', 'access-token')
base_headers['access-token'] = access_token
return base_headers
# 获取文本信息
def get_text(self, text, key):
text = json.loads(text)
values = jsonpath.jsonpath(text, key)
if values:
if len(values) == 1:
return values[0]
return values
# 断言校验
def assert_text(self, expected, text, key):
reality = self.get_text(text, key)
assert expected == reality, f'''
预期结果:{expected}
实际结果:{reality}
断言结果:{expected} != {reality}
'''
conf
conf.ini
[SERVERS]
devs = http://www.baidu.com/
tests = http://apihcc.fecmall.com/
online = http://www.jd.com/
[HEADERS]
access-token =
[BODY]
body =
set_conf.py
'''
配置和读取配置文件的内容,方便自动化测试的正常执行
'''
import configparser
import pathlib
# 获取配置文件
file = pathlib.Path(__file__).parents[0].resolve() / 'conf.ini'
# 配置项的读取
def read_conf(section, option):
conf = configparser.ConfigParser()
conf.read(file)
values = conf.get(section, option)
return values
# 配置项的写入
def write_conf(section, option, value):
conf = configparser.ConfigParser()
conf.read(file)
# 将指定的内容写入到conf之中
conf.set(section, option, value)
# 将写入操作进行保存
with open(file, 'w') as f:
conf.write(f)
test_cases
test_api.py
'''
接口测试用例
'''
import unittest
from ddt import file_data, ddt
from class35_interface_pytest.api_keys.api_keys import Api
from class35_interface_pytest.conf import set_conf
@ddt
class TestApi(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.api = Api()
# 清空测试过程中产生的数据内容
@classmethod
def tearDownClass(cls) -> None:
set_conf.write_conf('HEADERS', 'access-token', '')
# 登录
# @file_data('../test_data/login.yaml')
@file_data('../test_data/languages.yaml')
def test_01_login(self, **kwargs):
data = kwargs['login']
res = self.api.do_post(path=data['path'], data=data['data'])
txt = self.api.get_text(res.text, 'access-token')
# 将access-token写入到文件之中
set_conf.write_conf('HEADERS', 'access-token', txt)
print(res.text)
self.api.assert_text(data['expected'], res.text, 'status')
# 获取多语言list
# @file_data('../test_data/getList.yaml')
@file_data('../test_data/languages.yaml')
def test_02_getList(self, **kwargs):
data = kwargs['get_list']
res = self.api.do_get(path=data['path'])
print(res.text)
self.api.assert_text(data['expected'], res.text, 'code')
if __name__ == '__main__':
unittest.main()
test_demo.py
'''
全局变量的形态实现关联接口的数据传递:
全局变量的形态实现接口关联业务,最大的问题在于关联数据的传递会很麻烦。推荐自定义封装赋值的操作行为,减少赋值的工作量
'''
import unittest
import requests
from ddt import file_data, ddt
@ddt
class TestDemo(unittest.TestCase):
# 将关联数据和yaml中对应的数据进行关联,实现自动赋值
def assignment(self, values):
# 对yaml中的字典进行解析,有值的不再二次处理,无值的需要进行赋值操作
for key, value in values.items():
# 如果value是字典则继续解析到最终形态,如果不是字典则停止解析
if type(value) is dict:
self.assignment(value)
else:
# 解析到最后,value只会有有值和无值两种情况
if value: # 有值则不作任何操作
pass
else: # 无值情况下,进行赋值操作
values[key] = getattr(self, key)
return values
@classmethod
def setUpClass(cls):
cls.token = None
cls.ida = None
cls.name = None
cls.age = None
cls.hcc = None
def test_01_login(self):
TestDemo.token = 'token'
TestDemo.ida = 'ida'
TestDemo.name = 'name'
TestDemo.age = 'age'
TestDemo.hcc = 'hcc'
# @file_data('../test_data/test.yaml')
# def test_02_getToken(self, **kwargs):
# kwargs['headers']['token'] = self.token
# kwargs['data']['name'] = self.name
# kwargs['data']['ida'] = self.ida
# kwargs['data']['hcc'] = self.hcc
# kwargs['data']['age'] = self.age
# print(kwargs)
@file_data('../test_data/test.yaml')
def test_02(self, **kwargs):
print(self.assignment(kwargs))
if __name__ == '__main__':
unittest.main()
test_data
getList.yaml
-
path: v1/languages
expected: 200
languages.yaml
-
login:
path: v1/account/login
data:
username: admin
password: admin123
expected: success
get_list:
path: v1/languages
expected: 200
login.yaml
-
path: v1/account/login
data:
username: admin
password: admin123
expected: success
test.yaml
-
path: /hcc
headers:
token:
data:
name:
ida:
age:
hcc: