# coding=utf-8
"""
@Project :pachong-master
@File :file_operate.py
@Author :gaojs
@Date :2022/7/1 23:00
@Blogs : https://www.gaojs.com.cn
"""
import openpyxl as xl
import yaml
def read_excel(filepath, sheet_name):
"""
读取数据,将其转换成所需格式
:return:
"""
# 得到整个excel文档对象
wb = xl.load_workbook(filepath)
# 获取某个sheet工作表数据
sheet_data = wb[sheet_name]
# 定义空列表,用来存储多行数据,每行数据都是一个列表
data = []
# 得到总行数
lines_count = sheet_data.max_row
# 得到总列数
cols_count = sheet_data.max_column
for li in range(2, lines_count+1):
line = []
for co in range(1, cols_count+1):
cell = sheet_data.cell(li, co).value
if cell is None:
cell = ''
line.append(cell)
data.append(line)
return data
def write_excel(filepath, sheet_name, row, col, text):
"""
写入内容
:return:
"""
wb = xl.load_workbook(filepath)
sheet_data = wb[sheet_name]
# 写入数据
sheet_data.cell(row=row, column=col, value=text)
wb.save(filepath)
def read_yaml(filepath):
"""
读取yaml文件
:return:
"""
with open(filepath, mode='r', encoding='utf-8') as fin:
content = yaml.load(fin, Loader=yaml.FullLoader)
return content
def write_yaml(filepath, text):
"""
写入文件内容
:return:
"""
with open(filepath, mode='w', encoding='utf-8') as fin:
yaml.dump(text, fin, Dumper=yaml.Dumper)
if __name__ == '__main__':
# print(read_excel('./test_data.xlsx', '数据驱动数据'))
# write_excel('./test_data.xlsx', '数据驱动数据', row=6, col=6, text='gaojianshuai')
print(read_yaml('./test_data.yml').get('数据驱动数据'))
write_yaml('./test_data1.yml', {'userName': 'gaojs', 'password': '1234'})
# 数据驱动接口数据
数据驱动数据:
- ['admin', 1234, 200, 0, 'success']
- ['', 1234, 200, 1, '参数为空']
- ['admin', '', 200, 1, '参数为空']
# coding=utf-8
"""
@Project :pachong-master
@File :conftest.py
@Author :gaojs
@Date :2022/6/30 21:47
@Blogs : https://www.gaojs.com.cn
"""
from typing import List
import pytest
import requests
from 码同学.requests_study.cookie_study import login
@pytest.fixture(scope='session', autouse=True)
def login_and_logout():
print('在conftest.py中定义fixture,自动执行')
login(userName='admin', password='1234')
print('在档次执行测试中只执行一次,因为作用域是session')
yield
print('在当前执行测试只执行一次后置动作,因为作用域是session')
# 重写pytest的一个hook函数,处理pycharm插件界面显示的执行结果乱码
def pytest_collection_modifyitems(items:List["item"]):
for item in items:
item.name = item.name.encode("utf-8").decode("unicode-escape")
item._nodeid = item._nodeid.encode("utf-8").decode("unicode-escape")
@pytest.fixture(scope='module', autouse=True)
def VPN0():
print('在conftest.py中定义fixture,自动执行')
login(userName='admin', password='1234')
print('在当前每个用例执行一次,因为作用域是module')
yield
print('在当前每个用例执行后执行一次,因为作用域是module')
不能有中文
[pytest]
addopts = -sv -n auto --dist=loadfile
testpaths = ./
python_files = test*.py
python_classes = Test*
python_functions = test_*
# coding=utf-8
"""
@Project :pachong-master
@File :test_param_login.py
@Author :gaojs
@Date :2022/6/30 22:44
@Blogs : https://www.gaojs.com.cn
"""
import pytest
import requests
# 第一步:将测试数据转换成python中列表套列表的格式
from 码同学.requests_study.cookie_study import login
from 码同学.requests_study.put_api_study import post_update_phone_info
# 第二:使用pytest装饰器,将其传递给测试用例函数
brand = ['Apple', 'xiaomi', 'sanxing']
color = ['red', 'yellow', 'black']
memorySize = ['256G', '128G', '64G', '512G']
cpuCore=['8核', '4核', '16核']
expect_status_code = [200]
expect_code = ['0']
expect_message = ['更新成功']
@pytest.mark.parametrize('brand', brand)
@pytest.mark.parametrize('color', color)
@pytest.mark.parametrize('memorySize', memorySize)
@pytest.mark.parametrize('cpuCore', cpuCore)
@pytest.mark.parametrize('expect_status_code', expect_status_code)
@pytest.mark.parametrize('expect_code', expect_code)
@pytest.mark.parametrize('expect_message', expect_message)
def test_put(brand, color, memorySize, cpuCore, expect_status_code, expect_code, expect_message):
"""
笛卡尔积参数化
:return:
"""
resp = post_update_phone_info(brand=brand, color=color, memorySize=memorySize, cpuCore=cpuCore)
status_code = resp.status_code
assert status_code == expect_status_code
# 断言code
resp_json = resp.json()
code = resp_json['code']
assert code == expect_code
# message断言
result = resp_json['message']
assert result == expect_message
# 异常组合不适合笛卡尔积,只能对有效值多个值进行使用
# coding=utf-8
"""
@Project :pachong-master
@File :test_param_login.py
@Author :gaojs
@Date :2022/6/30 22:44
@Blogs : https://www.gaojs.com.cn
"""
import pytest
import requests
from ..datadriver.file_operate import read_yaml, read_excel
# 第一步:将测试数据转换成python中列表套列表的格式
from 码同学.requests_study.cookie_study import login
# 第一种数据给定:指定在文件中
# test_data = [
# ['admin', '1234', 200, '0', 'success'],
# ['', '1234', 200, '1', '参数为空'],
# ['admin', '', 200, '1', '参数为空']
# ]
# 第二种,通过调用file_operate文件中的方法读取excel数据
# test_data = read_excel(r'E:\爬虫\pachong-master\码同学\datadriver\test_data.xlsx', '数据驱动数据')
test_data = read_yaml(r'E:\爬虫\pachong-master\码同学\datadriver\test_data.yml').get('数据驱动数据')
print(test_data)
@pytest.mark.parametrize('userName, password, expect_status_code, expect_code, expect_message', test_data)
def test_login_param(userName, password, expect_status_code, expect_code, expect_message):
"""
数据驱动:登录测试
:return:
"""
resp = login(userName=userName, password=password)
status_code = resp.status_code
assert status_code == expect_status_code
# 断言code
resp_json = resp.json()
code = resp_json['code']
assert code == expect_code
# message断言
result = resp_json['message']
assert result == expect_message
# coding=utf-8
"""
@Project :pachong-master
@File :test_by_func.py
@Author :gaojs
@Date :2022/6/30 21:55
@Blogs : https://www.gaojs.com.cn
"""
# 以函数形式编写测试用例
# 测试用例
from 码同学.requests_study.cookie_study import login
def test_login():
"""
登录测试用例
:return:
"""
resp = login(userName='admin', password='1234')
status_code = resp.status_code
assert status_code == 200
# 业务断言,
resp_json = resp.json()
# print(resp_json)
code = resp_json['code']
assert code == '0'
result = resp_json['message']
assert result == 'success'
def test_login_userisnull():
"""
登录测试用例
:return:
"""
resp = login(userName='', password='1234')
status_code = resp.status_code
assert status_code == 200
# 业务断言,
resp_json = resp.json()
print(resp_json)
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '参数为空'
# 运行代码方式
"""
1.运行单个用例
pytest .\码同学\pytest_study\test_by_class.py::TestLogin::test_login_userisnull
2.运行整个类下 的所有用例
pytest -sv .\码同学\pytest_study\test_by_class.py
3.右键执行所有用例:光标放在所有第一个方法顶部
4.右键执行某一个用例:贯标放在对应的函数上
"""
# coding=utf-8
"""
@Project :pachong-master
@File :test_by_class.py
@Author :gaojs
@Date :2022/6/30 21:55
@Blogs : https://www.gaojs.com.cn
"""
# 以类形式编写测试用例
# 测试用例
from 码同学.requests_study.cookie_study import login
class TestLogin:
# 测试用例1
def test_login(self):
"""
登录测试用例
:return:
"""
resp = login(userName='admin', password='1234')
status_code = resp.status_code
assert status_code == 200
# 业务断言,
resp_json = resp.json()
# print(resp_json)
code = resp_json['code']
assert code == '0'
result = resp_json['message']
assert result == 'success'
# 测试用例2
def test_login_userisnull(self):
"""
登录测试用例
:return:
"""
resp = login(userName='', password='1234')
status_code = resp.status_code
assert status_code == 200
# 业务断言,
resp_json = resp.json()
print(resp_json)
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '参数为空'
# 运行代码方式
"""
1.运行单个用例
pytest .\码同学\pytest_study\test_by_class.py::TestLogin::test_login_userisnull
2.运行整个类下 的所有用例
pytest -sv .\码同学\pytest_study\test_by_class.py
3.右键执行所有用例
"""
setup_function
# coding=utf-8
"""
@Project :pachong-master
@File :test_prepost_module.py
@Author :gaojs
@Date :2022/6/30 22:18
@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录
from 码同学.requests_study.cookie_study import login, query
def setup_function():
print('\n************setup_function:在当前脚本文件中,每个用例执行之前,都会执行一次登陆**************')
# 登陆接口
login(userName='admin', password='1234')
def teardown_function():
print('***********teardown_function: 在当前脚本文件中,每个测试用例执行后,都会执行一次**************')
# 测试用例1:查询余额正确
def test_query():
"""
正常查询操作
:return:
"""
resp = query(userName='admin')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '0'
result = resp_json['message']
assert result == 'success'
# 测试用例2:错误的用户名
def test_query_error():
"""
正常查询操作
:return:
"""
resp = query(userName='gaojs')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '用户未登录'
setup_method
# coding=utf-8
"""
@Project :pachong-master
@File :test_prepost_module.py
@Author :gaojs
@Date :2022/6/30 22:18
@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录
import pytest
from 码同学.requests_study.cookie_study import login, query
class TestQuery:
def setup_method(self):
print('\n************setup_method:在当前类中,每条测试用例执行之前,都会执行一次登陆**************')
# 登陆接口
login(userName='admin', password='1234')
def teardown_method(self):
print('***********teardown_method: 在当前类中,每条测试用例执行之后,都会执行一次**************')
# 测试用例1:查询余额正确
def test_query(self):
"""
正常查询操作
:return:
"""
resp = query(userName='admin')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '0'
pytest.assume(code == '0', f'实际值:{code},期望值是0')
result = resp_json['message']
# assert result == 'success'
pytest.assume(result == 'success', f'实际值:{result},期望值是success')
# 测试用例2:错误的用户名
def test_query_error(self):
"""
正常查询操作
:return:
"""
resp = query(userName='gaojs')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '用户未登录'
setup_module
# coding=utf-8
"""
@Project :pachong-master
@File :test_prepost_module.py
@Author :gaojs
@Date :2022/6/30 22:18
@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录
from 码同学.requests_study.cookie_study import login, query
def setup_module():
print('\n************setup:在当前脚本文件中,所有执测试执行前,只执行一次登陆**************')
# 登陆接口
login(userName='admin', password='1234')
def teardown_module():
print('***********teardown: 在当前脚本文件中,所有执测试执行后,只执行一次**************')
# 测试用例1:查询余额正确
def test_query():
"""
正常查询操作
:return:
"""
resp = query(userName='admin')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '0'
result = resp_json['message']
assert result == 'success'
# 测试用例2:错误的用户名
def test_query_error():
"""
正常查询操作
:return:
"""
resp = query(userName='gaojs')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '用户未登录'
# coding=utf-8
"""
@Project :pachong-master
@File :test_prepost_module.py
@Author :gaojs
@Date :2022/6/30 22:18
@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录
import pytest
from 码同学.requests_study.cookie_study import login, query
# @pytest.fixture(scope='class', autouse=True)
# def login_and_logout():
# print('\n************setup_class:在当前类中,在每个类执行之前,都会执行一次登陆**************')
# login()
# yield
# print('***********teardown_class: 在当前类中,在每个类执行之后,都会执行一次**************')
class TestQuery:
# def setup_class(self):
# print('\n************setup_class:在当前类中,在每个类执行之前,都会执行一次登陆**************')
# # 登陆接口
# login(userName='admin', password='1234')
#
# def teardown_class(self):
# print('***********teardown_class: 在当前类中,在每个类执行之后,都会执行一次**************')
# 测试用例1:查询余额正确
def test_query(self, login_and_logout):
"""
正常查询操作
:return:
"""
resp = query(userName='admin')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '0'
result = resp_json['message']
assert result == 'success'
# 测试用例2:错误的用户名
def test_query_error(self, login_and_logout):
"""
正常查询操作
:return:
"""
resp = query(userName='gaojs')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '用户未登录'
class TestQuery1:
# 测试用例1:查询余额正确
def test_query1(self, login_and_logout):
"""
正常查询操作
:return:
"""
resp = query(userName='admin')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '0'
result = resp_json['message']
assert result == 'success'
# 测试用例2:错误的用户名
def test_query_error1(self, login_and_logout):
"""
正常查询操作
:return:
"""
resp = query(userName='gaojs')
status = resp.status_code
assert status == 200
resp_json = resp.json()
code = resp_json['code']
assert code == '1'
result = resp_json['message']
assert result == '用户未登录'
总结:
1.模块级别最大,因为不管是函数式测试用例,还是类方式的测试用例,都在一个模块中
2.函数级别仅仅是针对,函数式测试用例生效(setup_function()不能再类方式中使用,类方式中要使用setup_method())
3.类级别和方法级别,是针对于类方式编写的测试用例生效
4.setup和teardown是可以替换函数级别和方法级别的前置后置
1.运行单个用例
pytest .\码同学\pytest_study\test_by_class.py::TestLogin::test_login_userisnull
2.运行整个类下 的所有用例
pytest -sv .\码同学\pytest_study\test_by_class.py
3.右键执行所有用例:光标放在所有第一个方法顶部
4.右键执行某一个用例:贯标放在对应的函数上
异常组合不适合笛卡尔积,只能对有效值多个值进行使用
# coding=utf-8
"""
@Project :pachong-master
@File :cookie_study.py
@Author :gaojs
@Date :2022/6/28 22:50
@Blogs : https://www.gaojs.com.cn
"""
import requests
# 多个接口使用同一个session对象的话,他会自动的帮我们去管理和关联cookie
session = requests.session()
def login(userName='admin', password='1234'):
"""
登录操作
:return:
"""
url = 'http://localhost:9090/bank/api/login'
data = {
'userName': userName,
'password': password
}
rsp = session.post(url=url, data=data)
result = rsp.json().get('message')
return rsp
def query(userName='admin'):
"""
银行余额查询接口
:return:
"""
url = 'http://localhost:9090/bank/api/query'
params = {
'userName': userName
}
rsp = session.get(url=url, params=params)
print(rsp.text)
result = rsp.json().get('message')
print(result)
money_data = rsp.json().get('data')
print(money_data)
return rsp
login()
query()
# coding=utf-8
"""
@Project :pachong-master
@File :delete_api_study.py
@Author :gaojs
@Date :2022/6/28 23:26
@Blogs : https://www.gaojs.com.cn
"""
import requests
def delete_phone_info():
"""
put请求
更新手机信息
:return:
"""
url = 'http://localhost:9090/com/phone'
data = {
"brand": "Apple", "color": "red",
"memorySize": "256G", "cpuCore": "8核",
"price": "10080", "desc": "全新上市"
}
rsp = requests.delete(url=url, json=data)
print(rsp.text)
result = rsp.json().get('message')
print(result)
# coding=utf-8
"""
@Project :pachong-master
@File :file_upload_study.py
@Author :gaojs
@Date :2022/6/28 23:17
@Blogs : https://www.gaojs.com.cn
"""
import requests
session = requests.session()
def file_upload():
"""
上传文件
:return:
"""
url = 'http://localhost:9090/file/api/upload2'
file = {
'file': open(r'C:\Users\Administrator\Desktop\123.jpg', mode='rb')
}
rsp = session.post(url=url, files=file)
result = rsp.json().get('message')
print(result)
if __name__ == '__main__':
file_upload()
# coding=utf-8
"""
@Project :pachong-master
@File :post_api_study.py
@Author :gaojs
@Date :2022/6/28 22:43
@Blogs : https://www.gaojs.com.cn
"""
import requests
def post_api():
"""
post请求
:return:
"""
url = 'http://localhost:9090/com/login'
data = {
'userName': 'admin',
'password': '1234'
}
rsp = requests.post(url=url, data=data)
result = rsp.json().get('message')
print(result)
def post_add_phone_info():
"""
新增手机信息
:return:
"""
url = 'http://localhost:9090/com/phone'
data = {
"brand": "Huawei", "color": "yellow",
"memorySize": "64G", "cpuCore": "8核",
"price": "8848", "desc": "全新上市"
}
rsp = requests.post(url=url, json=data)
result = rsp.json().get('message')
print(result)
# coding=utf-8
"""
@Project :pachong-master
@File :put_api_study.py
@Author :gaojs
@Date :2022/6/28 22:49
@Blogs : https://www.gaojs.com.cn
"""
import requests
def post_update_phone_info(brand='Apple', color='red', memorySize='256G', cpuCore='8核'):
"""
put请求
更新手机信息
:return:
"""
url = 'http://localhost:9090/com/phone'
data = {
"brand": brand,
"color": color,
"memorySize": memorySize,
"cpuCore": cpuCore,
"price": "10080",
"desc": "全新上市"
}
rsp = requests.put(url=url, json=data)
result = rsp.json().get('message')
print(result)
return rsp
post_update_phone_info()
# coding=utf-8
"""
@Project :pachong-master
@File :token_study.py
@Author :gaojs
@Date :2022/6/28 23:01
@Blogs : https://www.gaojs.com.cn
"""
import requests
session = requests.session()
def login(userName='admin', password='1234'):
"""
获取token
:return:
"""
url = 'http://localhost:9090/bank/api/login2'
data = {
'userName': userName,
'password': password
}
rsp = session.post(url=url, data=data)
print(rsp.text)
return rsp
def post_api_token(userName='admin', password='1234'):
"""
获取token
:return:
"""
url = 'http://localhost:9090/bank/api/login2'
data = {
'userName': userName,
'password': password
}
rsp = session.post(url=url, data=data)
print(rsp.text)
msg = rsp.json().get('message')
print(msg)
global token
token = rsp.json().get('data')
print(token)
return token
def query_money():
"""
银行余额查询接口
:return:
"""
url = 'http://localhost:9090/bank/api/query2'
params = {
'userName': 'admin'
}
headers = {
'testfan-token': token
}
rsp = session.get(url=url, headers=headers, params=params)
print(rsp.text)
result = rsp.json().get('data')
print(result)
if __name__ == '__main__':
post_api_token()
query_money()
readME
总结:
requests库的请求方法参数众多,划分如下:
global全局参数使用:不通的函数中如果想使用的话就用global
查询参数就用params=params
表单参数就用data=data
json参数就用json=json
文件参数就用files=files
请求头信息headers就用headers=headers