目录
一、简介 3
二、 项目架构 3
2.1、业务结构 3
2.2、平台架构 4
三、开发框架选择 4
3.1、Web开发框架 4
3.2、数据库ORM 5
3.3、前端 5
四、项目结构 5
4.1 项目结构目录树 5
4.2 项目结构目录解析 6
五、数据库 6
5.1、SQLAlchemy数据库配置 6
5.2、建立数据库表 8
5.3、数据库操作 8
六、 路由和视图 9
6.1、定义方法 9
6.2、变量规则 10
6.3、HTTP 方法 11
6.4、模板渲染 11
七、 前端页面 11
7.1、HTML基本结构 11
7.2、表单结构 12
7.3、Jinja2模板渲染语法 13
7.3.1、变量 14
7.3.2、控制结构 14
7.3.3、模板继承 15
八、 前后台数据传递 16
8.1、注册/登录 17
8.2、权限控制 18
8.3、列表页数据获取 20
九、用例加载执行 21
9.1、单元执行 21
9.2、批量执行 22
该平台是一款基于CS模式的web服务平台,用于对测试用例的统一管理,集用例添加、编辑、删除、运行于一身,用例运行的核心机制采用的是httprunner
平台用例核心运行机制采用的是httprunner,而httprunner采用的Python语言,所以平台也顺势选用Python作为开发语言,Python web开发有两个主流框架Django和Flask。
l Django是一款重量级的Python开发web框架,功能齐全,不同的人用Django来开发,开发出来的东西基本架构都是一样的,
l Flask是一个轻量级的web框架,相对来说更加灵活,每个人开发出来的东西架构可能完全不一样。
l 对于团队级别的大型项目来说,比较适合选择Django,因为整个团队比较容易达成一致的架构,不会陷入无休止的会议讨论,里面很多东西不需要自己设计,拿来即用,快速开发。
l 对于个人开发的小项目来说,也可以用Django,也可以用Flask,用Flask的话,可以设计自己的项目架构,不必拘泥于Django的固定模式。对于以后进行功能扩展也比较容易开展。
l Flask对于加深Python学习有很大帮助,因为Flask不像Django很多东西都是现成的,需要自己去写
因此,基于以上的对比,选择Flask作为项目的开发框架。
采用SQLAlchemy,SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。选择SQLAlchemy一个原因是因为它是基于Python的开源框架,再就是使用比较广泛,教程多,遇到问题容易找到解决方法。
前端基本都是固定的HTML5,CSS,JavaScript,为了方便快速开发,选用一款前端框架bootstrap,脚本引入jQuery库。由于采用flask框架,因此模板渲染自然而然就是采用的jinja2.
E:.
│ .gitignore
│ config.py
│ manager.py
│ run.py
├─app
│ │ models.py
│ │ views.py
│ │ __init__.py
│ ├─static
│ │ ├─bootstrap
│ │ │ ├─css
│ │ │ │ bootstrap-theme.css
│ │ │ ├─fonts
│ │ │ │ glyphicons-halflings-regular.eot
│ │ │ └─js
│ │ │ bootstrap.js
│ │ └─image
│ │ bg.jpg
│ ├─templates
│ │ add_config.html
│ └─__pycache__
│ models.cpython-36.pyc
│ __init__.cpython-36.pyc
│
├─hrunner
│ │
│ ├─ssj_api
│ ├─ssj_share
│ ├─ssj_sync
│ ├─token
│ └─user_api
│
├─httprunner
│
├─tests
│
└─test
l .gitignore文件是放在项目的根目录,用来存放需要忽略的git提交文件
l config.py用来存放项目的一些配置信息
l manager.py用来存放一些通用的函数,数据库操作类
l app文件夹为项目的主应用
l models.py中用来存放数据库模型,所有的数据库表都在这里建立
l views.py中用来存放路由函数,所有的请求接口功能都是在这里定义的
l __init__.py中主要初始化一个应用的,里面除了import语句,只有一行代码app=Flask(__name__)
l static文件夹中用来存放一些网站的静态文件,如bootstrap框架的css,js模板,一些image背景图片,图标之类的
l templates文件夹中用来存放网站每个html页面
l test中是测试代码
每个网站都有大量数据,需要数据库支撑,本项目采用MySQL数据库,在项目开始前首先要建立一个项目对应的数据库SsjApiPlat,并且需要提前安装Python第三方库Flask-SQLAlchemy,在使用SQLAlchemy时需要对数据库进行配置。在进行配置之前需要用到应用,就需要提前导入应用和必要的库文件
from flask_sqlalchemy import SQLAlchemy
from Flask.SsjApiPlat2.app import app
因为Python3以后都是默认采用绝对引用,所以引用的路径要补全。
Flask-SQLAlchemy 扩展能够识别的配置键的清单:
SQLALCHEMY_DATABASE_URI |
用于连接数据的数据库。例如: · sqlite:////tmp/test.db · mysql://username:password@server/db |
SQLALCHEMY_BINDS |
一个映射绑定 (bind) 键到 SQLAlchemy 连接 URIs 的字典。 |
SQLALCHEMY_ECHO |
如果设置成 True,SQLAlchemy 将会记录所有 发到标准输出(stderr)的语句,这对调试很有帮助。 |
SQLALCHEMY_RECORD_QUERIES |
可以用于显式地禁用或者启用查询记录。查询记录 在调试或者测试模式下自动启用。 |
SQLALCHEMY_NATIVE_UNICODE |
可以用于显式地禁用支持原生的 unicode。这是 某些数据库适配器必须的(像在 Ubuntu 某些版本上的 PostgreSQL),当使用不合适的指定无编码的数据库 默认值时。 |
SQLALCHEMY_POOL_SIZE |
数据库连接池的大小。默认是数据库引擎的默认值 (通常是 5)。 |
SQLALCHEMY_POOL_TIMEOUT |
指定数据库连接池的超时时间。默认是 10。 |
SQLALCHEMY_POOL_RECYCLE |
自动回收连接的秒数。这对 MySQL 是必须的,默认 情况下 MySQL 会自动移除闲置 8 小时或者以上的连接。 需要注意地是如果使用 MySQL 的话, Flask-SQLAlchemy 会自动地设置这个值为 2 小时。 |
SQLALCHEMY_MAX_OVERFLOW |
控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。 |
SQLALCHEMY_TRACK_MODIFICATIONS |
如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它。 |
最主要的配置就是第一个SQLALCHEMY_DATABASE_URI,用于连接数据库,其实我们也只需要配置这一个键就可以了,其他的都可以选择默认。
SQLAlchemy 把一个引擎的源表示为一个连同设定引擎选项的可选字符串参数的 URI。URI 的形式是:
dialect+driver://username:password@host:port/database
该字符串中的许多部分是可选的。如果没有指定驱动器,会选择默认的(确保在这种情况下 不 包含 + )。
项目中的MySQL数据库配置如下:
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:123456@localhost:3306/ssjapiplat"
还需要添加一个SECRET_KEY,这个字段是为以后进行账号权限控制使用的
app.config['SECRET_KEY'] = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
如果你使用的是其他的数据库,可以参考下面的示例
Postgres:
postgresql://scott:tiger@localhost/mydatabase
MySQL:
mysql://scott:tiger@localhost/mydatabase
Oracle:
oracle://scott:[email protected]:1521/sidname
SQLite (注意开头的四个斜线):
sqlite:////absolute/path/to/foo.db
数据库表需要提前规划好,比如一个需要注册登陆的网站,就需要一个用户数据表,数据表的设计都是放在models模块中,SQLAlchemy设计数据表的方法如下:
class UserInfo(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
password = db.Column(db.String(80),)
def __init__(self, username, email, password):
self.username = username
self.email = email
self.password = password
def __repr__(self):
return '
最后调用db.create_all()来执行创建,在数据库中建立对应的数据表
l 增
userinfo = UserInfo(username=username,
email=email,
password=password
)
db.session.add(userinfo)
db.session.commit()
l 删
a= UserInfo.query.filter_by(username=username, password=password)
db.session.delete(a)
db.session.commit()
l 改
a= UserInfo.query.filter_by(username=username, password=password)
a.username = ‘jeo’
db.session.commit()
l 查
UserInfo.query.all()
UserInfo.query.filter_by(username=username, password=password).count()
UserInfo.query.with_entities(UserInfo.id).filter_by(username=username).all() #用来查询数据库表中某一字段,返回的是一个列表,列表中的元素是一个元组
在Flask中路由就是实际服务器的接口,视图就是实现该接口的函数,在Flask定义路由的最简便方式,是使用程序实例提供的app.route修饰器,把修饰的函数注册为路由
如:
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello World'
像index这样的函数为视图函数
如何访问路由?首先我们需要先启动路由,启动方法就是在main函数中执行app.run()即可,这样访问地址和端口都是使用的默认的,一般为127.0.0.1:8000,如果要从远程主机访问的话需要加入host参数如下设置
if __name__ == '__main__':
app.run(host='0.0.0.0')
要访问index,在浏览器输入127.0.0.1:5000/,回车即可,返回结果如下图所示
Hello页面,127.0.0.1:5000/hello
这里有一个需要注意的问题
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/projects)
def projects():
return 'The project page'
上面两个例子看似一样,但他们的结尾斜线的使用在URL定义中不同
第一个例子,如果在访问时,结尾不加斜线,那么会被Flask重定向到带斜线的规范URL去
第二个例子,如果在访问时,结尾加了斜线,那么访问时,会产生一个404not found的错误
所以,在编写路由时尽量在最后添加斜线
不仅如此!你可以构造含有动态部分的 URL,也可以在一个函数上附着多个规则。
要给 URL 添加变量部分,你可以把这些特殊的字段标记为
@app.route('/user/
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
```
## 程序请求上下文
### Flask从客户端收到请求,需让视图函数能访问一些对象,才能处理请求。为了避免大量可有可无的参数把视图函数弄的一团糟,Flask使用上下文把某些对象变为全局可访问。### 如:
```Python
from Flask import request
@app.route('/')
def index():
user=request.headers.get('User-Agent')
return 'your browser is %s' % user
HTTP (与 Web 应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET 请求,但是通过 route() 装饰器传递 methods 参数可以改变这个行为。这里有一些例子:
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
当我们打开一个登录页面时,http方法默认使用的是get,而当点击登录按钮时,会发起一个post的表单请求。
用 Python 生成 HTML 十分无趣,而且相当繁琐,因为你必须手动对 HTML 做转义来保证应用的安全。为此,Flask 配备了 Jinja2 模板引擎。
你可以直接使用 render_template() 方法来渲染模板。Flask中的render_template方法已经完全封装好了jinja的那一套模板渲染方法,你不需要再关心jinja中的environment对象,template对象和render方法,你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变量。这里有一个展示如何渲染模板的简例:
from flask import render_template
@app.route('/hello/')
@app.route('/hello/
def hello(name=None):
return render_template('hello.html', name=name)
我们所要关注的地方就是渲染方法传入的上下文参数和页面控制逻辑,这些将放在前端页面一节介绍
前端页面部分的用到的主要有三大块:HTML,CSS,JavaScript。页面样式和动作用到的CSS和JavaScript这里采用了一个前端的框架bootstrap。页面的变量及控制用jinja2来渲染。
下面是一个最简单的html5文档
文档内容......
以上文档保存成.html格式后用浏览器打开就是如下图所示
这个文档中包含6个标签元素,都是必备的最基本的标签
l 标签是用来告知web浏览器页面使用了哪个版本的HTML,HTML5还是HTML4或者其他版本
HTML5版本声明:
HTML4版本声明:
l 标签是告知浏览器这是一个html文档,是html文档最外层的元素
l
标签是所有头部元素的容器,里面必须要包含l
l
下面代码就是一个注册页面的表单,这里只贴出了body部分中的用户名一个输入框。
Form表单中所有属于用户输入的元素最终都会在提交表单时,作为post请求的data一起发送。Div是用来进行页面布局的块。他们都有class属性用来描述这是一个什么类型的控件,style属性对应的是css样式,这两个属性的值都可以使用bootstrap中预设的各种值。
最终点击最后一个div中的注册按钮会触发onclick属性的值(一个ajax请求函数,这个函数定义在
下面这个表单是登录页面的,只贴出了form一行,这个表单的请求方式与上面的注册页面是不一样的,表单中的action属性值指示了表单请求的url,method属性值指示了请求的方法