Python3+pytest框架系列---2
一、项目及框架搭建
1、项目环境工具
- python https://www.python.org/downloads/
- pycharm http://www.jetbrains.com/pycharm/
- git https://git-scm.com/download
2、配置
Pycharm配置
配置python解释器 :Settings -> Project -> Project Interpreter
配置git解释器: Settings -> Version Control -> Git
Pycharm+Git配置
配置github :Settings -> Version Control -> GitHub
创建github项目:https://github.com/
上传github :增加忽略文件需要 安装.ignore插件,上传需配置github
二、requests
1、requests介绍及简单使用
(1)Requests介绍
流行的接口http(s)请求工具
使用功能强大、简单方便、容易上手
(2)Requests简单使用
安装Requests包
$ pip3 install requests
简单使用
import requests
requests.get("http://www.baidu.com")
Requests请求返回介绍
r.status_code #响应状态
r.content #字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩
r.headers #以字典对象存储服务器响应头,若键不存在则返回None
r.json() #Requests中内置的JSON
r.url # 获取url r.encoding # 编码格式
r.cookies # 获取cookie
r.raw #返回原始响应体
r.text #字符串方式的响应体,会自动根据响应头部的字符编码进行
r.raise_for_status() #失败请求(非200响应)抛出异常
2、request用例编写
- 编写登录用例脚本
url = "http://172.17.0.139:5004/authorizations/"
data = {"username":"python", "password":"12345678"}
r= requests.post(url,json=data)
- 编写个人信息获取脚本
url = "http://172.17.0.139:5004/user/"
headers = '{"Authorization": "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUwNjMwOTksInVzZXJfaWQiOjEsImVtYWlsIj oiOTUyNjczNjM4QHFxLmNvbSIsInVzZXJuYW1lIjoicHl0aG9uIn0.f3GdeSnzb3UGsw1p1ejZ1rNLaaiBOAHUnN8_pq8LDE"}'
r = requests.get(url,headers=headers)
- 商品列表数据
url = "http://172.17.0.139:5004/categories/115/skus"
data = { "page":"1", "page_size": "10", "ordering": "create_time"}
r = requests.get(url, json=data)
print(r.text)
print(r.json)
添加到购物车
def cart():
url = "http://172.17.0.139:5004/cart/"
data = { "sku_id": "3", "count": "1", "selected": "true"}
headers = {"Authorization": "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjU4NTU2NzcsInVzZXJfaWQiOjEsImVtYWlsIj oiOTUyNjczNjM4QHFxLmNvbSIsInVzZXJuYW1lIjoicHl0aG9uIn0.yotHV8wMX7MKHyioFDaGnrjTDTAYsLB0R 8Qsungw_ms"}
r = requests.post(url, json=data,headers=headers)
print(r.text)
print(r.json)
def get_cart():
url = "http://172.17.0.139:5004/cart/"
headers = { "Authorization": "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjU4NTU2NzcsInVzZXJfaWQiOjEsImVtYWlsIj oiOTUyNjczNjM4QHFxLmNvbSIsInVzZXJuYW1lIjoicHl0aG9uIn0.yotHV8wMX7MKHyioFDaGnrjTDTAYsLB0R 8Qsungw_ms"}
r = requests.get(url, headers=headers)
print(r.text)
print(r.json)
保存订单
def orders():
url = "http://172.17.0.139:5004/orders/"
data = { "address": "1", "pay_method": "1"}
headers = {"Authorization": "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjU4NTU2NzcsInVzZXJfaWQiOjEsImVtYWlsIj oiOTUyNjczNjM4QHFxLmNvbSIsInVzZXJuYW1lIjoicHl0aG9uIn0.yotHV8wMX7MKHyioFDaGnrjTDTAYsLB0R 8Qsungw_ms"}
r = requests.post(url, json=data,headers=headers)
print(r.text)
print(r.json)
3、Requests方法封装
封装requests get方法
#1、创建封装get方法
def requests_get(url,headers):
#2、发送requests get请求
r = requests.get(url,headers = headers)
#3、获取结果相应内容
code = r.status_code
try:
body = r.json()
except Exception as e:
body = r.text
#4、内容存到字典
res = dict()
res["code"] = code
res["body"] = body
#5、字典返回
return res
封闭requests post方法
#post方法封装
#1、创建post方法
def requests_post(url,json=None,headers=None):
#2、发送post请求
r= requests.post(url,json=json,headers=headers)
#3、获取结果内容
code = r.status_code
try:
body = r.json()
except Exception as e:
body = r.text
#4、内容存到字典
res = dict()
res["code"] = code
res["body"] = body
#5、字典返回
return res
封装requests公共方法
- 增加cookies,headers参数
- 根据参数method判断get/post请求
def requests_api(self,url,data = None,json=None,headers=None,cookies=None,method="get"):
if method =="get":
#get请求
self.log.debug("发送get请求")
r = requests.get(url, data = data, json=json, headers=headers,cookies=cookies)
elif method == "post":
#post请求
self.log.debug("发送post请求")
r = requests.post(url,data = data, json=json, headers=headers,cookies=cookies)
#2. 重复的内容,复制进来
#获取结果内容
code = r.status_code
try:
body = r.json()
except Exception as e:
body = r.text
#内容存到字典
res = dict()
res["code"] = code
res["body"] = body
#字典返回
return res
重构get方法
- 调用公共方法request_api,
- 参数:固定参数:url,method
- 其它参数: **args
#1、定义方法
def get(self,url,**kwargs):
#2、定义参数
#url,json,headers,cookies,method
#3、调用公共方法
return self.requests_api(url,method="get",**kwargs)
重构post方法
- 调用公共方法request_api,
- 参数:固定参数:url,method
- 其它参数: **args
def post(self,url,**kwargs):
#2、定义参数 #url,json,headers,cookies,method
#3、调用公共方法
return self.requests_api(url,method="post",**kwargs)
三、配置文件
1、Yaml 介绍及安装
-
Yaml 介绍
Yaml 是一种所有编程语言可用的友好的数据序列化标准。语法和其他高阶语言类似,并且可以简单表达字 典、列表和其他基本数据类型的形态。语法规则如下:
1. 大小写敏感。
2. 使用缩进表示层级关系。
3. 使用空格键缩进,而非Tab键缩进
4. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可。
5. 文件中的字符串不需要使用引号标注,但若字符串包含有特殊字符则需用引号标注;
6. 注释标识为# 官网:https://yaml.org/
-
Yaml 安装
$ pip3 install PyYaml
-
Yaml 快速体验
字典{"name": "test_yaml", "result", "success"}写成Yaml的形式,并输出结果 结构通过空格缩进来展示。
列表里的项用"-"来代表,字典里的键值对用":"分隔.
示例函数:
data.yaml
name: "test_yaml"
result: "success"
demo.py
import yaml
with open("./data.yaml",'r') as f:
data = yaml.safe_load(f)
print(data)
运行结果:
{'name': 'test_yaml', 'result': 'success'}
2、Yaml 字典和列表介绍
(1)字典
字典里的键值对用":"分隔.
示例: {"name": "test_yaml", "result", "success"}
name: "test_yaml"
age: "success"
总结: 字典直接写key和value,每一个键值对占一行。 : 后面要有空格
(2)列表
一组按序排列的值(简称 "序列或列表")
数组前加有 “-” 符号,符号与值之间需用空格分隔
示例:["a", "b", "c"]
- "a"
- "b"
- "c"
列表中的元素需要用 -来表示
每一个元素前面都有一个 -,后面接元素内容
3、Yaml 字典和列表基本操作
(1)字典嵌套字典
需求:
{
person1:{
"name": "xiaoming",
"age": "18"
},
person2: {
"name": "xiaohong",
"age": "20"
}
}
示例:
person1:
name: "xiaoming"
age: "18"
person2:
name: "xiaohong"
age: "20"
(2)字典嵌套列表
需求:
{person: ["1", "2", "3"]}
示例 :
persion:
- "1"
- "2"
- "3"
(3)列表嵌套字典
需求:
[{ "username1": "test1" }, { "password1": "111", "username2": "test2", "password2": "222" }]
示例:
- username1: "test1"
- password1: "111"
username2: "test2"
password2: "222"
(4)列表嵌套列表
需求:
[["a","b","c"],["1","2","3"]]
示例:
-
- "a"
- "b"
- "c"
-
- "1"
- "2"
- "3"
注意:
- pycharm会自动将yaml中的tab转化成空格。但是不能复制”tab键“,不会进行转化。
- 同级别左侧必须要对齐,少个空格无所谓。
4、读取yaml文件
(1)读取单个Yaml文档
yaml文档
#data.yaml
"用户名称": "test123"
"密码": "123456"
示例函数:demo.py 中文问题(windows): encoding='utf-8
import yaml
# 打开要读取的文件,中文 encoding='utf-8'
with open("./data.yaml", 'r', encoding='utf-8') ) as f:
# 加载文件内容
data = yaml.safe_load(f)
# 打印结果
print(data)
读取实际上就是先使用 with open 的形式获取文件对象,再使用 yaml 中的 load 方法加载这个文件对象,通过 过load方法,一个字符串变成了一个字典
结果: {'用户名称': 'test123', '密码': '123456'}
(2)读取多个Yaml文档
多个文档在一个yaml文件,使用 --- 分隔方式来分段
yaml文档:
---
"用户名称1": "test123"
"密码": "123456"
---
"用户名称2": "test456"
"密码": "123456"
示例:
import yaml
with open("./data.yaml",'r') as f:
data = yaml.safe_load_all(f)
for i in data:
print(i)
结果:
{'用户名称1': 'test123', '密码': '123456'}
{'用户名称2': 'test456', '密码': '123456'}
5、yaml封装
import os
import yaml
#1、创建类
class YamlReader:
#2、初始化,文件是否存在
def __init__(self,yamlf):
if os.path.exists(yamlf):
self.yamlf = yamlf
else:
raise FileNotFoundError("文件不存在")
self._data = None
self._data_all = None
#3、yaml读取
#单个文档读取
def data(self):
#第一次调用data,读取yaml文档,如果不是,直接返回之前保存的数据
if not self._data:
with open(self.yamlf,"rb") as f:
self._data = yaml.safe_load(f)
return self._data
#多个文档读取
def data_all(self):
#第一次调用data,读取yaml文档,如果不是,直接返回之前保存的数据
if not self._data_all:
with open(self.yamlf,"rb") as f:
self._data_all = list(yaml.safe_load_all(f))
return self._data_all
6、配置文件设置
(1)配置文件conf.yaml
BASE:
#log等级
log_level: "debug"
#扩展名
log_extension: ".log"
test:
url: "http://XXX"
case_file: "testdata.xlsx"
case_sheet: "接口测试"
(2)基本目录配置
import os
from utils.YamlUtil import YamlReader
#1、获取项目基本目录
#获取当前项目的绝对路径
current = os.path.abspath(__file__)
#print(current)
BASE_DIR = os.path.dirname(os.path.dirname(current))
#print(BASE_DIR)
#定义config目录的路径
_config_path = BASE_DIR + os.sep + "config"
#定义data目录的路径
_data_path = BASE_DIR + os.sep + "data"
#定义conf.yml文件的路径
_config_file = _config_path + os.sep +"conf.yml"
#定义db_conf.yml路径
_db_config_file = _config_path + os.sep +"db_conf.yml"
#定义logs文件路径
_log_path = BASE_DIR + os.sep + "logs"
#定义report目录的路径
_report_path = BASE_DIR + os.sep + "report"
def get_report_path():
"""
获取report绝对路径
:return:
"""
return _report_path
def get_data_path():
return _data_path
def get_db_config_file():
return _db_config_file
def get_config_path():
return _config_path
def get_config_file():
return _config_file
def get_log_path():
return _log_path
(3)conf.yml配置文件读取
#2、读取配置文件
class ConfigYaml:
#初始yaml读取配置文件
def __init__(self):
self.config = YamlReader(get_config_file()).data()
self.db_config = YamlReader(get_db_config_file()).data()
#获取测试用例excel名称
def get_excel_file(self):
return self.config["BASE"]["test"]["case_file"]
#获取测试用例sheet名称
def get_excel_sheet(self):
return self.config["BASE"]["test"]["case_sheet"]
#获取环境的URL
def get_conf_url(self):
return self.config["BASE"]["test"]["url"]
#获取日志级别
def get_conf_log(self):
return self.config["BASE"]["log_level"]
#获取文件扩展名
def get_conf_log_extension(self):
return self.config["BASE"]["log_extension"]
#根据db_alias获取该名称下的数据库信息
def get_db_conf_info(self,db_alias):
return self.db_config[db_alias]
#获取邮件配置相关信息
def get_email_info(self):
return self.config["email"]