我的编程空间,编程开发者的网络收藏夹
学习永远不晚

flask + Python3 实现的的

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

flask + Python3 实现的的

**背景: 1.平时测试接口,总是现写代码,对测试用例的管理,以及测试报告的管理持久化做的不够,
2.工作中移动端开发和后端开发总是不能并行进行,需要一个mock的依赖来让他们并行开发。
3.同时让自己锻炼去开发测试平台,掌握flask开发程序,提高自己的业务水平。

整体思路: 1.利用flask+bootstrap来进行web界面开发,对接口,接口测试用例,定时任务,测试报告的持续集成。
2.IAPTest支持接口用例管理,接口多用例测试,支持定时测试任务,测试报告持久化
3.目前mock服务支持单一path,定时任务可以开启暂停多用例执行,定时任务执行后自动发送测试报告,多用例的单次执行,单接口的调试功能。对测试环境的管理
下面来看下最后的效果图,以及附上github开源地址。

测试环境管理界面:

flask + Python3 实现的的API自动化测试平台----  IAPTest接口测试平台

定时任务界面:
flask + Python3 实现的的API自动化测试平台----  IAPTest接口测试平台

mock界面

flask + Python3 实现的的API自动化测试平台----  IAPTest接口测试平台

测试报告界面

flask + Python3 实现的的API自动化测试平台----  IAPTest接口测试平台

用例管理界面

flask + Python3 实现的的API自动化测试平台----  IAPTest接口测试平台

接口管理界面

flask + Python3 实现的的API自动化测试平台----  IAPTest接口测试平台

核心代码分享区:

定时任务对应视图开发

class AddtimingtaskView(MethodView):br/>@login_required
def get(self):
return render_template('addtimingtasks.html')br/>@login_required
def post(self):
taskname=request.form['taskname']
tinmingtime=request.form['time']
to_email_data=request.form['to_email']
cao_email=request.form['cao_email']
weihu=request.form['weihu']
if taskname =='':
flash('任务名不能为空!')
return render_template('addtimingtasks.html')
if tinmingtime =='':
flash('任务执行时间不能为空!')
return render_template('addtimingtasks.html')
if to_email_data=='':
flash('发送给谁邮件不能为空!')
return render_template('addtimingtasks.html')
if weihu=='':
flash('维护人邮件不能为空!')
return render_template('addtimingtasks.html')
taskname_is = Task.query.filter_by(taskname=taskname).first()
if taskname_is:
flash('任务已经存在请重新填写!')
return render_template('addtimingtasks.html')
new_task=Task(taskname=taskname,taskstart=tinmingtime,taskrepor_to=to_email_data,taskrepor_cao=cao_email,task_make_email=weihu,
makeuser=current_user.id)
db.session.add(new_task)
try:
db.session.commit()
flash('添加定时任务成功')
return redirect(url_for('timingtask'))
except Exception as e:
db.session.rollback()
flash('添加过程貌似异常艰难!')
return redirect(url_for('addtimingtasks'))
return render_template('addtimingtasks.html')
class Editmingtaskview(MethodView):
br/>@login_required
def get(self,id):
task_one=Task.query.filter_by(id=id).first()
procjet=Project.query.all()
if not task_one:
flash('你编辑的不存在')
return redirect(url_for('timingtask'))
return render_template('Edittimingtasks.html',task_one=task_one,porjects=procjet)
def post(self,id):
task_one = Task.query.filter_by(id=id).first()
procjet = Project.query.all()
taskname = request.form['taskname']
tinmingtime = request.form['time']
to_email_data = request.form['to_email']
cao_email = request.form['cao_email']
weihu = request.form['weihu']
if taskname =='':
flash('任务名不能为空!')
return render_template('addtimingtasks.html')
if tinmingtime =='':
flash('任务执行时间不能为空!')
return render_template('addtimingtasks.html')
if to_email_data=='':
flash('发送给谁邮件不能为空!')
return render_template('addtimingtasks.html')
if weihu=='':
flash('维护人邮件不能为空!')
return render_template('addtimingtasks.html')
task_one.taskname=taskname
task_one.taskrepor_to=to_email_data
task_one.taskrepor_cao=cao_email
task_one.task_make_email=weihu
task_one.makeuser=current_user.id
try:
db.session.commit()
flash('编辑成功')
return redirect(url_for('timingtask'))
except:
db.session.rollback()
flash('编辑出现问题!')
return redirect(url_for('timingtask'))
return render_template('Edittimingtasks.html', task_one=task_one,porjects=procjet)
class DeteleTaskViee(MethodView):
def get(self,id):
task_one = Task.query.filter_by(id=id).first()
if not task_one:
flash('你编辑的不存在')
return redirect(url_for('timingtask'))
if task_one.status==True:
flash('已经删除')
return redirect(url_for('timingtask'))
task_one.status=True
try:
db.session.commit()
flash('删除任务成功')
return redirect(url_for('timingtask'))
except:
db.session.rollback()
flash('删除任务休息了')
return redirect(url_for('timingtask'))
br/>@app.route('/gettest',methods=['POST'])
@login_required
def gettest():#ajax获取项目的测试用例
projec=(request.get_data('project')).decode('utf-8')
if not projec:
return []
proje=Project.query.filter_by(project_name=str(projec)).first()
if not proje:
return []
testyong=InterfaceTest.query.filter_by(projects_id=proje.id).all()
testyong_list=[]
for i in testyong:
testyong_list.append({'name':i.Interface_name,'id':i.id})
return jsonify({'data':testyong_list})
class TestforTaskView(MethodView):#为测试任务添加测试用例
def get(self,id):
procjet = Project.query.all()
task_one=Task.query.filter_by(id=id).first()
return render_template('addtestyongfortask.html',task_one=task_one,procjets=procjet)
def post(self,id):
procjet = Project.query.all()
task_one = Task.query.filter_by(id=id).first()
proc_test=request.form.get('project')
if proc_test =='':
flash(u'不能不添加测试项目!')
return render_template('addtestyongfortask.html', task_one=task_one, procjets=procjet)
test_yongli=request.form.getlist('testyongli')
if test_yongli=='':
flash(u'亲你见过只有测试项目没有测试用例的测试任务吗!')
return render_template('addtestyongfortask.html', task_one=task_one, procjets=procjet)
for oldtask in task_one.interface.all():
task_one.interface.remove(oldtask)
task_one.prject=Project.query.filter_by(project_name=proc_test).first().id
for yongli in test_yongli:
task_one.interface.append(InterfaceTest.query.filter_by(id=yongli).first())
db.session.add(task_one)
try:
db.session.commit()
flash('任务更新用例成功')
return redirect(url_for('timingtask'))
except:
flash('任务更新用例失败')
return redirect(url_for('timingtask'))
return render_template('addtestyongfortask.html', task_one=task_one, procjets=procjet)
class StartTaskView(MethodView):#开始定时任务
br/>@login_required
def get(self,id):
task=Task.query.filter_by(id=id).first()
if len(task.interface.all())<=1:
flash('定时任务执行过程的测试用例为多用例,请你谅解')
return redirect(url_for('timingtask'))
try:
scheduler.add_job(func=addtask, id=str(id), args=str(id),trigger=eval(task.taskstart),replace_existing=True)
task.yunxing_status='启动'
db.session.commit()
flash(u'定时任务启动成功!')
return redirect(url_for('timingtask'))
except Exception as e:
flash(u'定时任务启动失败!请检查任务的各项内容各项内容是否正常')
return redirect(url_for('timingtask'))
class ZantingtaskView(MethodView):#暂停定时任务
br/>@login_required
def get(self,id):
task = Task.query.filter_by(id=id).first()
try:
scheduler.pause_job(str(id))
task.yunxing_status = '暂停'
db.session.commit()
flash(u'定时任务暂停成功!')
return redirect(url_for('timingtask'))
except:
task.yunxing_status = '创建'
db.session.commit()
flash(u'定时任务暂停失败!已经为您初始化')
return redirect(url_for('timingtask'))
class HuifutaskView(MethodView):#回复定时任务
br/>@login_required
def get(self,id):
task = Task.query.filter_by(id=id).first()
try:
scheduler.resume_job(str(id))
task.yunxing_status='启动'
db.session.commit()
flash(u'定时任务恢复成功!')
return redirect(url_for('timingtask'))
except:
task.yunxing_status = '创建'
db.session.commit()
flash(u'定时任务恢复失败!已经为您初始化')
return redirect(url_for('timingtask'))
class YichuTaskView(MethodView):#移除定时任务
br/>@login_required
def get(self,id):
task = Task.query.filter_by(id=id).first()
try:
scheduler.delete_job(str(id))
task.yunxing_status='关闭'
db.session.commit()
flash(u'定时任务移除成功!')
return redirect(url_for('timingtask'))
except:
task.yunxing_status = '创建'
db.session.commit()
flash(u'定时任务移除失败!已经为您初始化')
return redirect(url_for('timingtask'))







定时任务所执行的func代码

def addtask(id):#定时任务执行的时候所用的函数
in_id=int(id)
task=Task.query.filter_by(id=in_id).first()
starttime = datetime.datetime.now()
star = time.time()
day = time.strftime("%Y%m%d%H%M", time.localtime(time.time()))
basedir = os.path.abspath(os.path.dirname(file))
file_dir = os.path.join(basedir, 'upload')
file = os.path.join(file_dir, (day + '.log'))
if os.path.exists(file) is False:
os.system('touch %s' % file)
filepath = os.path.join(file_dir, (day + '.html'))
if os.path.exists(filepath) is False:
os.system(r'touch %s' % filepath)
projecct_list = []
model_list = []
Interface_name_list = []
Interface_url_list = []
Interface_meth_list = []
Interface_pase_list = []
Interface_assert_list = []
Interface_headers_list = []
id_list = []
for task_yongli in task.interface.all():
id_list.append(task_yongli.id)
projecct_list.append(task_yongli.projects)
model_list.append(task_yongli.models)
Interface_url_list.append(task_yongli.Interface_url)
Interface_name_list.append(task_yongli.Interface_name)
Interface_meth_list.append(task_yongli.Interface_meth)
Interface_pase_list.append(task_yongli.Interface_pase)
Interface_assert_list.append(task_yongli.Interface_assert)
Interface_headers_list.append(task_yongli.Interface_headers)
apitest = ApiTestCase(Interface_url_list, Interface_meth_list, Interface_pase_list, Interface_assert_list, file,
Interface_headers_list)
result_toal, result_pass, result_fail, relusts, bask_list = apitest.testapi()
endtime = datetime.datetime.now()
end = time.time()
createHtml(titles=u'接口测试报告', filepath=filepath, starttime=starttime, endtime=endtime, passge=result_pass,
fail=result_fail, id=id_list, name=projecct_list, headers=Interface_headers_list,
coneent=Interface_url_list, url=Interface_meth_list, meth=Interface_pase_list,
yuqi=Interface_assert_list, json=bask_list, relusts=relusts)
hour = end - star
user_id = User.query.filter_by(role_id=2).first().id
new_reust = TestResult(Test_user_id=user_id, test_num=result_toal, pass_num=result_pass, fail_num=result_fail,
test_time=starttime, hour_time=hour, test_rep=(day + '.html'), test_log=(day + '.log'))
email = EmailReport.query.filter_by(role_id=2, default_set=True).first()
send_emails(sender=email.send_email, receivers=task.taskrepor_to, password=email.send_email_password,
smtp=email.stmp_email, port=email.port, fujian1=file, fujian2=filepath, subject=u'%s自动用例执行测试报告' % day,
url='%stest_rep'%(request.url_root))
db.session.add(new_reust)
db.session.commit()

mock服务的一个请求方式的代码

1 class MakemockserverView(MethodView):#做一个mock服务
2 def get(self,path):#get请求方法
3 huoqupath=Mockserver.query.filter_by(path=path,status=True).first()
4 heders=request.headers
5 method=request.method
6 if not huoqupath:
7 abort(404)
8 if method.lower() !=huoqupath.methods:
9 return jsonify({'code':'-1','message':'请求方式错误!','data':''})
10 if huoqupath.is_headers==True:
11 if comp_dict(heders,huoqupath.headers) ==True:
12 if huoqupath.ischeck==True:
13 paerm = request.values.to_dict()
14 if dict_par(paerm,huoqupath.params)==True:
15 if huoqupath.rebacktype == 'json':
16 try:
17 json_fan = json.dumps(huoqupath.fanhui)
18 return jsonify({'code': '1', 'message': 'successs', 'data': json_fan})
19 except:
20 return jsonify({'code': '-2', 'message': '你写入的返回不能正常json!请检查', 'data': ''})
21 elif huoqupath.rebacktype == 'xml':
22 response = make_response(huoqupath.fanhui)
23 response.content_type = 'application/xml'
24 return response
25 else:
26 return jsonify({'code': '-2', 'message': '你写入的类型目前系统不支持', 'data': ''})
27 else:
28 return jsonify({'code': '-4', 'message': '你输入的参数不正确', 'data': ''})
29 else:
30 if huoqupath.rebacktype=='json':
31 try:
32 json_fan=json.dumps(huoqupath.fanhui)
33 return jsonify({'code': '1', 'message': 'successs', 'data':json_fan})
34 except:
35 return jsonify({'code': '-2', 'message': '你写入的返回不能正常json!请检查', 'data': ''})
36 elif huoqupath.rebacktype =='xml':
37 response=make_response(huoqupath.fanhui)
38 response.content_type='application/xml'
39 return response
40 else:
41 return jsonify({'code': '-2', 'message': '你写入的类型目前系统不支持', 'data': ''})
42 else:
43 return jsonify({'code': '-3', 'message': '安全校验失败!', 'data': ''})
44 if huoqupath.ischeck == True:
45 paerm = request.values.to_dict()
46 if dict_par(paerm, huoqupath.params) == True:
47 if huoqupath.rebacktype == 'json':
48 try:
49 json_fan = json.dumps(huoqupath.fanhui)
50 return jsonify({'code': '1', 'message': 'successs', 'data': json_fan})
51 except:
52 return jsonify({'code': '-2', 'message': '你写入的返回不能正常json!请检查', 'data': ''})
53 elif huoqupath.rebacktype == 'xml':
54 response = make_response(huoqupath.fanhui)
55 response.content_type = 'application/xml'
56 return response
57 else:
58 return jsonify({'code': '-2', 'message': '你写入的类型目前系统不支持', 'data': ''})
59 else:
60 return jsonify({'code': '-4', 'message': '你输入的参数不正确', 'data': ''})
61 else:
62 if huoqupath.rebacktype == 'json':
63 try:
64 json_fan = json.dumps(huoqupath.fanhui)
65 return jsonify({'code': '1', 'message': 'successs', 'data': json_fan})
66 except:
67 return jsonify({'code': '-2', 'message': '你写入的返回不能正常json!请检查', 'data': ''})
68 elif huoqupath.rebacktype == 'xml':
69 response = make_response(huoqupath.fanhui)
70 response.content_type = 'application/xml'
71 return response
72 else:
73 return jsonify({'code': '-2', 'message': '你写入的类型目前系统不支持', 'data': ''}) #

开源地址:https://github.com/liwanlei/FXTest

使用说明:

1.依赖包为requirements.txt文件下的,可能部分不全,需要什么可以自己使用中增加。
2.目前由于考虑后续迁移内部使用的话,所以移除了注册功能,改为管理员后台添加方式,默认登录:liwanlei 密码:liwanlei
3.部分功能调试还存在一定的问题,欢迎各位多提宝贵意见,

部分功能欠缺:

1.定时任务的持久化,现在处理容易受到运行过程中的宕机等情况重新启动服务器的定时任务全部需要开启
2、mock接口只能支持单一的path

  1. 测试环境没有改为动态配置,动态支持。目前测试环境管理以及上线
    4。部分地方可能还会有不严谨性,但是工具可以使用。
    5、目前仅支持 http请求中的json格式的,
    6.大家可以多提意见,后续会优化,最近一直熬夜加班可能有些消息不能及时回复,还望谅解。

有问题可以联系我:QQ:952943386 email:leileili126@163.com qq群:194704520 新群:683894834

微信打赏

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

flask + Python3 实现的的

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

flask + Python3 实现的的

**背景: 1.平时测试接口,总是现写代码,对测试用例的管理,以及测试报告的管理持久化做的不够,2.工作中移动端开发和后端开发总是不能并行进行,需要一个mock的依赖来让他们并行开发。3.同时让自己锻炼去开发测试平台,掌握flask开发程序
2023-01-31

python3-开发进阶Flask的基础

一、概述最大的特点:短小精悍、可拓展强的一个Web框架。注意点:上下文管理机制,依赖wsgi:werkzurg 模块二、前奏学习werkzurg先来回顾一个知识点:一个类加括号会执行__init__方法,一个对象加括号执行__call__方
2023-01-30

DES算法的python3实现

DES原理 这里不予以复述, 有很多优秀的博客原理可以参考这篇博客https://www.cnblogs.com/songwenlong/p/5944139.html1. 主函数框架DES 函数 传入参数为text(明文 或者 密文)ke
2023-01-31

Flask中jinja2的继承怎么实现

这篇文章主要介绍Flask中jinja2的继承怎么实现,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!在继承的使用上,我们最早接触的是父类和子类的继承。不过Flask框架中的继承要简单一些,只要有一个原文件,便可以对其
2023-06-14

Python3实现简单的http ser

前端的开发的html给我们的时候,由于内部有一些ajax请求的.json的数据,需要在一个web server中查看,每次放到http服务器太麻烦。还是直接用python造一个最方便。最简单的,直接用python3 -m http.serv
2023-01-31

python3中@dataclass的实现示例

Python3中的@dataclass装饰器用于简化数据类的创建,通过自动生成必要的方法,如init、repr和eq,简化代码并提高可读性。它支持init、repr、eq、order、unsafe_hash和frozen等参数,提供各种自定义选项。尽管@dataclass易于使用,但其也仅适用于简单数据类,不能自定义特殊方法,因此可能不适合所有用例。
python3中@dataclass的实现示例
2024-04-02

Flask中跨域访问的实现方法

这篇文章将为大家详细讲解有关Flask中跨域访问的实现方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在我们访问不同的服务器时,就会涉及到了跨域的问题。因为不同域名之间是无法进行交流的,然后跨域就打破了
2023-06-14

flask中的蓝图实现模块化的应用

Blueprint    蓝图的基本设想是当它们注册到应用上时,它们记录将会被执行的操作。 当分派请求和生成从一个端点到另一个的 URL 时,Flask 会关联蓝图中的视图函数。    简单来说,Blueprint 是一个存储操作方法的容器
2023-01-30

如何在Flask中实现jinja2的继承

如何在Flask中实现jinja2的继承?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、说明Jinja2中最强大的部分是模板继承。通过模板继承,我们可以创建一个基本(框架)文
2023-06-06

Flask中基于Token的身份认证的实现

本文主要介绍了Flask中基于Token的身份认证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-02-20

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录