文章目录
- 1.项目整体架构
- 2.config.ini文件
- 3.readConfig.py文件
- 4.api层
- 5.case层
- 6.tools层
- 7.data层
- 8.log层
- 9.report层
- 10.run_suite.py文件
- 11.发送邮件
1.项目整体架构
api:接口层 case:业务层 data:数据层 log:日志 report:报告 tools:工具层 config.ini:配置文件 readConfig.py:读取配置文件方法 run_suite.py:整体运行用例入口 send_email.py:发送邮件
2.config.ini文件
说明:该文件为配置文件,用来存放一些不怎么改变的东西,例如:ip地址、数据库参数、接口地址、发送邮件人等等 创建config.ini文件,右键点击项目->选择New->点击File 填写config.ini,点击ok 例如一个接口是这样的,我们假设它为登录接口: https://www.tokenin.cn/api/v2/report/hotMarkList 那我们可以把他拆分开,前面的是ip地址,后面的是项目文件地址,因为所有这个项目的接口前面的ip地址肯定是一样的,只是后面的项目文件地址不同罢了,我们分开的话,如果需要更换测试环境,只需要更改前面的ip地址就可以了
注意:在这个配置文件里千万不要写备注,如果写了就会报错!
3.readConfig.py文件
作用:读取配置文件(config.ini) 创建常规的python文件就可以了,这个就不需要我教了吧。。。 代码附上
import configparser
import os
"""
读取配置文件
"""
# 创建对象
read_ini = configparser.ConfigParser()
# 获取当前文件路径
current_file_path = os.path.dirname(os.path.abspath(__file__))
# 读取配置文件内容
read_ini.read(current_file_path + "/config.ini")
# 接口拼接
def url_join(api):
url = "http://" + get_host() + api
return url
# IP地址
def get_host():
return read_ini['API']['host']
# 登录接口
def get_hotMarkList():
return url_join(read_ini['API']['hotMarkList'])
if __name__ == '__main__':
print(get_hotMarkList())
看到没,拼接出来了吧,一模一样,这样设计的话维护会省事很多!还不点个赞! 那么如何在api层case层进行调用呢,别着急,慢慢往下看
4.api层
作用:该地址的请求方式,返回结果 文件格式:api_接口名称
get请求方式:不需要token等其他信息
import requests
from readConfig import *
# 登录接口
class ApiHotMarkList(object):
def api_hot_mark_list(self, username, password):
params = {"username": username, "password": password}
return requests.get(get_hotMarkList(), params=params)
if __name__ == '__main__':
api = ApiHotMarkList()
a = api.api_hot_mark_list("登录账号", "密码")
print(a.json())
git请求方式:需要token等其他信息(具体需要什么去问开发人员,他比你清楚,或者你也可以使用postman请求成功后,把Headers里面的隐藏内容整出来加到headers里,然后一个一个去除,看看到底需要哪个)
import requests
from readConfig import *
# 登录接口
class ApiHotMarkList(object):
def api_hot_mark_list(self, username, password, token, cookie):
params = {"username": username, "password": password}
headers = {"Authorization": token, "Cookie": cookie}
return requests.get(get_hotMarkList(), headers=headers, params=params)
if __name__ == '__main__':
api = ApiHotMarkList()
a = api.api_hot_mark_list("登录账号", "密码", "token值", "cookie值")
print(a.json())
post请求:
import requests
from readConfig import *
# 登录接口
class ApiHotMarkList(object):
def api_hot_mark_list(self, username, password, token, cookie):
data = {"username": username, "password": password}
headers = {"Authorization": token, "Cookie": cookie}
return requests.post(get_hotMarkList(), headers=headers, data=data)
if __name__ == '__main__':
api = ApiHotMarkList()
a = api.api_hot_mark_list("登录账号", "密码", "token值", "cookie值")
print(a.json())
下面再讲个小技巧,比如有这么个业务需求:登录->获取用户列表信息 那么这个获取用户列表信息接口肯定需要登录成功后才能请求,那么我们就需要一个登录成功接口,如何进行呢?请继续往下看。 首先在config.ini文件里面填写登录成功的账号密码,如下: 然后在readConfig.py文件里面写获取成功登录账号密码的方法,如下: 然后在api层的登录接口类文件里写成功登录接口方法
import requests
from readConfig import *
# 登录接口类
class ApiHotMarkList(object):
# 登录接口
def api_hot_mark_list(self, username, password):
data = {"username": username, "password": password}
return requests.post(get_hotMarkList(), data=data)
# 成功登录接口方法
def api__hot_mark_list_success(self, username, password):
data = {"username": username, "password": password}
login_value = requests.post(get_hotMarkList(), headers=headers, data=data)
# 获取cookie
cookie_dic = requests.utils.dict_from_cookiejar(login_value.cookies)
cookie = self.get_cookie(cookie_dic)
return login_value, cookie
# cookie遍历方法
def get_cookie(self, cookie_dic):
for key in cookie_dic.keys():
for value in cookie_dic.values():
return key + "=" + value
if __name__ == '__main__':
api = ApiHotMarkList()
a = api.api_hot_mark_list("登录账号", "密码")
print(a.json())
然后在case调用就ok啦
5.case层
作用:业务方法层,也可以理解为用例层 文件名:必须以test开头,后面加上数字,然后加上用例名称
import unittest
from parameterized import parameterized
from readConfig import *
from api.api_hot_mark_list import *
from tool.get_logger import GetLogger
from tool.read_json import read_json
log = GetLogger.get_logger()
class TestLogin(unittest.TestCase):
@parameterized.expand(read_json("login.json"))
def test_login(self, username, password, status_code, expect):
# 调用成功登录方法
login_success = ApiHotMarkList().api__hot_mark_list_success(get_username(), get_password())
log.info("成功登录接口,返回信息为:{}".format(login_success.json()))
# 断言状态码
self.assertEqual(status_code, login_success.json()['status'])
# 断言响应信息
self.assertEqual(expect, login_success.json()['message'])
# 调用登录方法
login = ApiHotMarkList().api_hot_mark_list(username, password)
log.info("登录接口,返回信息为:{}".format(login.json()))
# 断言状态码
self.assertEqual(status_code, login.json()['status'])
# 断言响应信息
self.assertEqual(expect, login.json()['message'])
if __name__ == '__main__':
unittest.main()
6.tools层
下面我截图的时候写错了,应该是tools,因为工具有很多嘛 作用:提供一些工具方法,如:读取json、读取报告、日志等等 日志:get_logger.py
import logging.handlers
import os
import time
class GetLogger:
__logger = None
@classmethod
def get_logger(cls):
if cls.__logger is None:
# 获取日志器
cls.__logger = logging.getLogger()
# 设置日志器级别
cls.__logger.setLevel(logging.INFO)
# 当前文件路径
current_file_path = os.path.dirname(os.path.abspath(__file__))
# 当前文件所在文件夹路径
current_file_dir_path = os.path.dirname(current_file_path)
file = current_file_dir_path + os.sep + "log" + os.sep + "{}.log".format(time.strftime("%Y-%m-%d"))
# 获取处理器 文件-以时间分割
"""
filename:文件路径及文件名
maxBytes:最大字节,1024 * 1024为1M,达到200M压缩
backupCount:备份的日志数量(备份7个,多余的删除)
encoding:编码格式
"""
th = logging.handlers.RotatingFileHandler(filename=file,
maxBytes=1024 * 1024 * 200,
backupCount=7,
encoding="utf-8")
# 设置格式器
fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s [%(funcName)s:%(lineno)d] - %(message)s"
fm = logging.Formatter(fmt)
# 将格式器添加到处理器 文件
th.setFormatter(fm)
# 将处理器添加到日志器
cls.__logger.addHandler(th)
return cls.__logger
if __name__ == '__main__':
log = GetLogger.get_logger()
for i in range(1000):
log.info("测试打印日志")
读取报告:read_html.py
import os
import re
import time
# 读取报告html数据
def read_html():
# 当前文件路径
current_file_path = os.path.dirname(os.path.abspath(__file__))
# 当前文件所在文件夹路径
current_file_dir_path = os.path.dirname(current_file_path)
file_path = current_file_dir_path + "/report/" + '{}.html'.format(time.strftime("%Y-%m-%d"))
with open(file_path, 'r', encoding='utf-8') as f:
error_log = f.read() # 读取html网页
pattren = re.compile(
"<tr id='total_row'>.*?<td>Total</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td> </td>",
re.S) # 正则表达式
r_list = pattren.findall(error_log) # 正则匹配文件内容
return r_list
if __name__ == '__main__':
print(read_html()[0][0])
读取json文件:read_json.py
import json
import os
# 读取json数据
def read_json(filename):
# 定义空列表 组装测试数据
arr = []
# 当前文件路径
current_file_path = os.path.dirname(os.path.abspath(__file__))
# 当前文件所在文件夹路径
current_file_dir_path = os.path.dirname(current_file_path)
file_path = current_file_dir_path + "/data/" + filename
# 打开json文件并获取文件流
with open(file_path, "r", encoding="utf-8")as f:
# 遍历 调用yaml.safe_load(f).values()方法
for datas in json.load(f).values():
arr.append(tuple(datas.values()))
# 返回 结果
return arr
if __name__ == '__main__':
print(read_json("login.json"))
7.data层
作用:以json格式存放数据(也可以根据自己喜好用其他格式文件存放数据)
8.log层
作用:存放日志
9.report层
作用:存放报告
10.run_suite.py文件
作用:整个程序运行入口
import unittest
import time
from tools.HTMLTestRunner import HTMLTestRunner
"""
用例整体运行入口
"""
# 组装测试套件
suite = unittest.defaultTestLoader.discover("./case", pattern="test*.py")
# 指定报告存放路径及文件名称
file_path = "./report/{}.html".format(time.strftime("%Y-%m-%d"))
# 运行测试套件并生成测试报告
with open(file_path, "wb")as f:
HTMLTestRunner(stream=f, title="自定义报告标题").run(suite)
11.发送邮件
作用:发送邮件
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time
from datetime import date
from readConfig import *
from tools.get_logger import GetLogger
from tools.read_html import read_html
log = GetLogger.get_logger()
date = date.today()
# 发送邮件
def send_mail(body):
try:
# 邮件正文是MIMEText
msg = MIMEText(body, 'html', 'utf-8')
# 邮件对象
msg['Subject'] = Header("发送邮件的标题".format(date), 'utf-8').encode() # 标题
msg['From'] = Header(u'{} <{}>'.format('发件人邮箱,例如:xiaoming@qq.com', sender)) # 发件人
msg['To'] = Header(u'收件人 <%s>' % recipient) # 发送的用户
msg['date'] = time.strftime("%a,%d %b %Y %H:%M:%S %z") # 发送时间日期
# 发送邮件
smtp = smtplib.SMTP()
smtp.connect('smtp.exmail.qq.com', 25) # 邮箱服务器,需查看服务器是否开启25端口
smtp.login(username, password) # 登录邮箱
smtp.sendmail(sender, recipient.split(','), msg.as_string()) # 发送者和接收者
smtp.quit()
log.info("邮件已发出,注意查收!")
except Exception as e:
log.error("邮件发送失败!".format(e))
# 发件箱用户名
username = get_email_username()
# 发件箱密码
password = get_email_password()
# 发件人邮箱
sender = get_email_sender()
# 收件人邮箱
recipient = get_email_recipient()
# 报告地址
report = get_email_report_url().format(date)
body = """
<p>本次接口自动化执行的测试环境为:{}</p>
<p>总共执行用例{}条,其中pass={}条,fail={}条,error={}条。</p>
<p>详情请查看报告:{}</p>
""".format(get_host(), read_html()[0][0], read_html()[0][1], read_html()[0][2], read_html()[0][3], report)
send_mail(body)
get_email_username()、get_email_password()、get_email_sender()、get_email_recipient()、get_email_report_url()都是调用的readConfig文件里的方法从config.ini文件里获取的,上面有详细介绍。
这次就分享到这里吧,有问题联系我就好,写这篇文章一是总结,二是希望能给迷茫的你一种思路,谢谢大家!