python自动化自动化测试平台开发:4.后端开发之用例的储存和查看
Posted new nm个对象
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python自动化自动化测试平台开发:4.后端开发之用例的储存和查看相关的知识,希望对你有一定的参考价值。
1.需求讲解
我们这个测试平台的主要功能有:上传储存用例,查看用例,运行用例,下载用例,上传测试报告等。
2.储存用例功能
2.1 创建用例表
(1)普通创建
第一步:创建app.py,用来启动一个flask服务
from flask import Flask
import conf
from flask_restful import Api,Resource
# 实例化一个Flask对象,用于启动flask服务
app = Flask(__name__)
# 添加配置文件
app.config.from_object(conf)
# 实例化flask_restful对象
api = Api(app)
# 设置用例储存视图函数
class TestCaseStoreView(Resource):
def get(self):
return '666'
api.add_resource(TestCaseStoreView, '/', endpoint='testcase_store')
if __name__ == "__main__":
app.run(debug=True,host='127.0.0.1',port=5055)
第二步:创建conf.py文件,用于项目的配置文件
"""
flask项目的配置文件
"""
# 数据库连接配置
HOSTNAME = '192.168.1.104'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'ouyi1994'
DATABASE = 'auto_test_frame'
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
SQLALCHEMY_TRACK_MODIFICATIONS = True
第三步:创建models.py文件,用于创建用例表
"""
使用flask_sqlalchemy模块声明数据库表
"""
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from app import app
# 实例化一个SQLAlchemy对象,用于操作数据库
db = SQLAlchemy(app)
class TestCaseModel(db.Model):
"""
用例表模型类
"""
__tablename__ = 'testcase'
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # id,主键
name = db.Column(db.String(30), unique=True, nullable=False) # 用例名
description = db.Column(db.String(200), unique=False, nullable=True) # 描述
file_path = db.Column(db.String(200), unique=True, nullable=False) # 用例文件路径
update_time = db.Column(db.DateTime, default=datetime.now()) # 更新时间
if __name__ == "__main__":
db.create_all()
(2)优化db和数据库表初始化
db是SQLAlchemy的一个实例化对象,用于操作数据库。所以我们在项目中会经常将db对象导入到其他文件中操作。为了防止导入db时,因为循环导入报错。我们可以将db对象放置在一个单独的第三方文件中存放。
第一步:新建一个exit.py文件,用于生成db对象。
"""
中间文件
"""
from flask_sqlalchemy import SQLAlchemy
# 实例化一个SQLAlchemy对象,用于操作数据库
db = SQLAlchemy()
使用该文件可以有效防止引用冲突
第二步:创建app.py,用来启动一个flask服务
from flask import Flask
import conf
from flask_restful import Api,Resource
from exit import db
# 实例化一个Flask对象,用于启动flask服务
app = Flask(__name__)
# 添加配置文件
app.config.from_object(conf)
# 实例化flask_restful对象
api = Api(app)
# 将SQLAlchemy对象db关联到app
db.init_app(app)
# 设置用例储存视图函数
class TestCaseStoreView(Resource):
def get(self):
return '666'
api.add_resource(TestCaseStoreView, '/', endpoint='testcase_store')
if __name__ == "__main__":
app.run(debug=True,host='127.0.0.1',port=5055)
第三步:创建models.py文件,用于创建用例表
"""
使用flask_sqlalchemy模块声明数据库表
"""
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from exit import db
class TestCaseModel(db.Model):
"""
用例表模型类
"""
__tablename__ = 'testcase'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(30), unique=True, nullable=False)
description = db.Column(db.String(200), unique=False, nullable=True)
file_path = db.Column(db.String(200), unique=True, nullable=False)
update_time = db.Column(db.DateTime, default=datetime.now())
使用Flask_Migrate和flask_script来完成数据库的初始化和迁移
因为我们在项目开发中会频繁的改动数据库类结构,使用Flask_Migrate和flask_script可以非常方便的来完成数据库的初始化和迁移管理。所有的迁移操作其实都是Alembic做的,能跟踪模型的变化,并将变化映射到数据库中。
创建manage.py文件,用来完成数据库的管理。
"""
用于数据库初始化
"""
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from exit import db
from app import app
from models import TestCaseModel # 将需要初始化或者迁移的表模型类导入到该文件中
manage = Manager(app)
Migrate(app,db)
manage.add_command('db',MigrateCommand)
if __name__ == '__main__':
manage.run()
- 在命令行执行
python manage.py db init
生成数据表初始化的迁移文件migrates
- 在命令行执行
python manage.py db migrate
,自动检测模型,生成迁移脚本。 - 在命令行
python manage.py db upgrade
,将迁移脚本的操作映射到数据库中。
2.2 实现储存用例的功能
(1)接口定义
(2)普通方式实现接口
编辑app.py文件
import os
from datetime import datetime
from flask import Flask, request
import conf
from flask_restful import Api, Resource
from exit import db
from models import TestCaseModel
# 实例化一个Flask对象,用于启动flask服务
app = Flask(__name__)
# 添加配置文件
app.config.from_object(conf)
# 实例化flask_restful对象
api = Api(app)
# 将SQLAlchemy对象db关联到app
db.init_app(app)
# 设置用例储存视图函数
class TestCaseStoreView(Resource):
def post(self):
name = request.form.get('name') # 获取请求参数:name
description = request.form.get('description') # 获取请求参数:description
test_file = request.files.get('test_file') # 获取请求参数:test_file
test_file_name = test_file.filename # 用例文件名。
# 判断name参数是否符合规定
if name is not None and isinstance(name,str):
# 判断test_file参数是否符合规定
if test_file is not None and test_file_name.endswith('.py'):
# 判断description参数是否为空
if description is not None:
# 判断判断description参数是否为str类型
if isinstance(description,str):
now = datetime.now().strftime('%Y-%m-%d-%H%M%S') # 生成时间戳
now_path = os.getcwd() # 获取当前目录路径
test_file.save(f'./{now}_{test_file_name}') # 保存用例文件到当前目录路径
file_path = os.path.join(now_path, f'{now}_{test_file_name}') # 拼接出用例文件路径
testcase = TestCaseModel(name=name, file_path=file_path,description=description)
# 保存到数据库
db.session.add(testcase)
db.session.commit()
return jsonify({
'code': 200,
'message': 'success'
})
else:
return jsonify({
'code': 404,
'message': 'description必须为str类型'
})
else:
now = datetime.now().strftime('%Y-%m-%d-%H%M%S') # 生成时间戳
now_path = os.getcwd() # 获取当前目录路径
test_file.save(f'./{now}_{test_file_name}') # 保存用例文件到当前目录路径
file_path = os.path.join(now_path,f'{now}_{test_file_name}') # 拼接出用例文件路径
testcase = TestCaseModel(name=name,file_path=file_path)
# 保存到数据库
db.session.add(testcase)
db.session.commit()
return jsonify({
'code':200,
'message':'success'
})
else:
return jsonify({
'code': 404,
'message': 'test_file参数不能为空,且必须为python文件'
})
else:
return jsonify({
'code':404,
'message':'name参数不能为空,且必须为str类型'
})
api.add_resource(TestCaseStoreView, '/testcase_store/', endpoint='testcase_store')
if __name__ == "__main__":
app.run(debug=True,host='127.0.0.1',port=5055)
我们使用postman来构造数据访问接口,看接口功能是否实现。
结果如下:
(3)优化请求参数校验
-
在上面的接口实现中,我们需要使用了if语句来校验前端传过来的参数。这种方式是不可取的,因为会使得我们的代码是否冗余。我们可以看到这个接口中只有3个参数,确使用了大量的if语句来进行校验。
-
我们可以使用flask-wtf来校验前端参数。
新建一个form.py文件,来进行参数的校验工作。
from wtforms import Form, StringField, FileField
from wtforms.validators import Length, InputRequired, ValidationError
from flask_wtf.file import FileRequired
# 校验用例储存请求参数
class TestCaseForm(Form):
name = StringField(validators=[Length(max=30, message='参数name不合法,参数长度不能大于30'),
InputRequired(message='参数name不能为空')
])
description = StringField(validators=[Length(max=200, message='参数description不合法,参数长度不能大于200')])
test_file = FileField(validators=[FileRequired(message='必须上传用例文件')])
def validate_test_file(self, field):
"""自定义test_file验证器"""
if not field.data.filename.endswith('.py'): # field.data获取需要校验的参数值,这里为上传的文件对象
raise ValidationError('用例文件必须为python文件') # 使用ValidationError抛出提示信息
修改app.py文件:
import os
from datetime import datetime
from flask import Flask, request, jsonify
import conf
from flask_restful import Api, Resource
from exit import db
from forms import TestCaseForm, GetTestCaseForm
from models import TestCaseModel
from werkzeug.datastructures import CombinedMultiDict
# 实例化一个Flask对象,用于启动flask服务
app = Flask(__name__)
# 添加配置文件
app.config.from_object(conf)
# 实例化flask_restful对象
api = Api(app)
# 将SQLAlchemy对象db关联到app
db.init_app(app)
# 设置用例储存视图函数
class TestCaseStoreView(Resource):
def post(self):
now = datetime.now().strftime('%Y-%m-%d-%H%M%S') # 生成时间戳
now_path = os.getcwd() # 获取当前目录路径
# 实例化TestCaseForm对象,用于参数校验。其参数为需要校验的参数字典列表
# CombinedMultiDict将两个属性组合起来传给校验器
form = TestCaseForm(CombinedMultiDict([request.form,request.files]))
if form.validate():
# 参数校验通过
name = form.name.data # 获取参数name的值
description = form.description.data # 获取参数description的值
test_file = form.test_file.data # 获取用例文件test_file对象
# 判断name是否已在数据库中存在
name_fag = db.session.query(TestCaseModel).filter(TestCaseModel.name==name).first()
if name_fag is None:
if description is not None:
# 保存用例文件
file_path = os.path.join(now_path, f'./case_files/{now}_{test_file.filename}')
test_file.save(file_path)
# 保存数据库
testcase = TestCaseModel(name=name,description=description,file_path=file_path)
db.session.add(testcase)
db.session.commit()
res = {
'code': 200,
'message': 'success'
}
return jsonify(res)
else:
# 保存用例文件
file_path = os.path.join(now_path, f'./case_files/{now}_{test_file.filename}')
test_file.save(file_path)
# 保存数据库
testcase = TestCaseModel(name=name, file_path=file_path)
db.session.add(testcase)
db.session.commit()
res = {
'code': 200,
'message': 'success'
}
return jsonify(res)
else:
res = {
'code': 404,
'message': '用例名字不能重复'
}
return jsonify(res)
else:
# 参数校验不通过
res = {
'code': 404,
'message': form.errors
}
return jsonify(res)
api.add_resource(TestCaseStoreView, '/testcase_store/', endpoint='testcase_store')
if __name__ == "__main__":
app.run(debug=True,host='127.0.0.1',port=5055)
运行结果如下:
3.查询用例功能
3.1 接口分析
3.2 实现接口
修改form.py文件
from wtforms import Form, StringField, FileField, IntegerField
from wtforms.validators import Length, InputRequired, ValidationError
from flask_wtf.file import FileRequired
# 校验用例储存请求参数
class TestCaseForm(Form):
name = StringField(validators=[Length(max=30, message='用例名字不合法,参数长度不能大于30'),
InputRequired(message='用例名字不能为空')
])
description = StringField(validators=[Length(max=200, message='用例描述不合法,参数长度不能大于200')])
test_file = FileField(validators=[FileRequired(message='必须上传用例文件')])
def validate_test_file(self, field):
"""自定义test_file验证器"""
if not field.data.filename.endswith('.py'): # field.data获取需要校验的参数值,这里为上传的文件对象
raise ValidationError('用例文件必须为python文件') # 使用ValidationError抛出提示信息
class GetTestCaseForm(Form):
id = IntegerField(validators=[InputRequired('用例id不能为空')])
修改app.py
import os
from datetime import datetime
from flask import Flask, request, jsonify
import conf
from flask_restful import Api, Resource
from exit import db
from forms import TestCaseForm, GetTestCaseForm
from models import TestCaseModel
from werkzeug.datastructures import CombinedMultiDict
# 实例化一个Flask对象,用于启动flask服务
app = Flask(__name__)
# 添加配置文件
app.config.from_object(conf)
# 实例化flask_restful对象
api = Api(app)
# 将SQLAlchemy对象db关联到app
db.init_app(app)
# 设置用例储存视图函数
class TestCaseStoreView(Resource):
def post(self):
now = datetime.now().strftime('%Y-%m-%d-%H%M%S') # 生成时间戳
now_path = os.getcwdpython自动化自动化测试平台开发:5.后端开发之用例文件下载,执行用例,查询用例执行状态
python自动化自动化测试平台开发:2.flask技术讲解上
python自动化自动化测试平台开发:3.flask技术讲解上