使用Flask搭建基于unittest的简单用例挑选及执行平台
在用例组织上,unittest的Test Suite的拥有非常好的灵活性,然而Test Suite一般要提前编制好,添加和组织用例必须使用代码,不方便使用。
本文使用 Flask + unittest.TestSuite + pickle搭建一个简单的unittest用例挑选和执行平台。
思路:
添加Test Suite: 使用discover()发现所有测试用例 -> 挑选用例 并生成Test Suite对象 -> 使用pickle.dump()序列化成文件 保存
执行Test Suite: 使用os.listdir()得到Test Suite列表 -> 使用pickle.load()反序列化成TestSuite对象 -> 执行TestSuite并生成报告
需要安装 Flask, pip install flask
在你的测试框架或用例同级目录下建立dashboard目录,结构如下
- dashboard
- suites 序列化的Test Suite文件目录
- templates 页面模板
- app.py
- test
- case 用例目录
新建app.py
作为我们的接口服务文件
这里我们只实现3个页面:
- 添加用例 suite_add
- 用例列表(可以选择suite执行)suite_list
- 报告页面 report
使用Flask写接口(页面)的大致套路
# 1. 导入包
from flask import Flask # Flask类,使用flask框架的基本类
from flask import request # 请求对象,用于获取请求参数
from flask import render_template # 用于渲染模板,并返回客户端一个html页面
from flask import redirect # 用于跳转到其他url
# 2. 实例化Flask类
app = Flask(__name__) # 使用当前模块实例化一个Flask对象,app是自定义的变量(后面使用要一致)
# 3. 编写接口(页面)并挂载访问地址,指定允许的请求方法
@app.route("/suite_add", methods=["GET", "POST"] # 接口(页面)地址为/suite_add, 支持GET和POST
def suite_add():
if request.method == 'POST': # POST方法用来处理添加
.....
return redirect("/") # 添加后跳转到 首页
return render_template("suite_add.html") # 如果是GET方法,渲染返回suite_add页面
# 4. 运行调试
if __name__ == '__main__':
app.run()
suite_add这个接口的实现逻辑为:
- 使用unittest的discover遍历并抽取所有用例返回给客户端(GET请求)
- 获取到客户端挑选的用例并生成unittest的TestSuite对象
- 根据客户端传的TestSuite名称,序列化成指定名称的文件并保存
代码如下:
from flask import Flask # Flask类,使用flask框架的基本类
from flask import request # 请求对象,用于获取请求参数
from flask import render_template # 用于渲染模板,并返回客户端一个html页面
from flask import redirect # 用于跳转到其他url
import os # 用于组装绝对路径
import unittest
import pickle # 序列化方法
# 一些要使用到的目录绝对路径
app_dir = os.path.dirname(os.path.abspath(__file__)) # dashborad目录
case_dir = os.path.join(os.path.dirname(app_dir), 'test', 'case') # 测试用例目录
suite_dir = os.path.join(app_dir, 'suites') # 测试套件目录
def collect(): # 收集用例并组成Test Suite
suite = unittest.TestSuite() # 新建Test Suite
def _collect(tests): # 由于unittest discover得到的TestSuite中包含了目录及子目录的路径,这里只把所有的用例抽取出来
if isinstance(tests, unittest.TestSuite):
if tests.countTestCases() != 0:
for i in tests:
_collect(i)
else:
suite.addTest(tests)
_collect(unittest.defaultTestLoader.discover(case_dir))
return suite
app = Flask(__name__) # 使用当前模块实例化一个Flask对象,app是自定义的变量(后面使用要一致)
@app.route("/suite_add", methods=["GET", "POST"] # 接口(页面)地址为/suite_add, 支持GET和POST
def suite_add():
tests = [] # 用例集合
for case in collect():
tests.append(case.id()) # 遍历testsuite中的用例,通过case.id()拿到用例名
if request.method == 'POST': # POST方法用来处理添加
suite_name = request.form.get("suite_name") # 从前端获取需要新建的testsuite名称
cases = request.form.getlist("cases") # 获取到前端选择的用例列表
suite = unittest.defaultTestLoader.loadTestsFromNames(cases) # 通过用例名列表生成TestSuite
with open(os.path.join(suite_dir, suite_name+".testsuite"), 'wb') as f: # 序列化并保存TestSuite
pickle.dump(suite, f)
return redirect("/") # 添加后跳转到 首页
return render_template("suite_add.html") # 如果是GET方法,渲染返回suite_add页面
if __name__ == '__main__': # 运行接口方法
app.run()
templates/suite_add.html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增Test Suite</title>
</head>
<body>
<h1>新增Test Suite</h1>
<form action="#" method="post">
标题:<input type="text" name="suite_name">
<h4>选择用例</h4>
{% for test in tests%}
<div><input type="checkbox" id="cases" name="cases" value="{{test}}">{{test}}</div>
{% endfor %}
<div><input type="submit" value="保存"></div>
</form>
</body>
</html>
执行后访问 http://127.0.0.1:5000/suite_add
标题输入suite1,选择用例,点击添加会在dashboard/suites下生成suite1.testsuite文件
由于添加后跳转到"/",这个接口(页面)还没实现,所以会报错,我们现在来实现suite列表, 思路:
- 使用os.listdir()遍历suites目录下的.testsuite文件并渲染到页面上
在app.py中添加
from HTMLTestReportCN import HTMLTestRunner # 这个是生成html报告的文件,放在app.py同级即可
@app.route("/", methods=['GET', 'POST'])
def suite_list():
suite_list = [suite.split(".")[0] for suite in os.listdir('suites') if suite.endswith(".testsuite")] # 遍历并去掉.testsuite扩展名
if request.method == 'POST': # 执行testsuite方法
suite_name = request.form.get("suite")
import sys;sys.path.append(case_dir) # 反序列化必须将 用例目录添加到sys.path中
with open(os.path.join(suite_dir, suite_name+".testsuite"), 'rb') as f: # 反序列化并得到TestSuite对象
suite = pickle.load(f)
with open(report_file, 'wb') as f: # 执行TestSuite并在templates目录中生成html文件
result = HTMLTestRunner(stream=f, title="Api Test", description="测试描述", tester="卡卡").run(suite)
return redirect("/report") # 显示报告
return render_template('suite_list.html', suite_list=suite_list) # GET方法返回suite列表页面
suite_list页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Test Suite列表</h1>
<a href="/suite_add">添加Test Suite</a>
<br>
<form action="#" method="post">
{% for suite in suite_list %}
<input type="radio" name="suite" value="{{suite}}">{{ suite }}
<br>
{% endfor %}
<input type="submit" value="执行">
</form>
</body>
</html>
显示报告方法(报告必须生成在templates目录下)
@app.route("/report", methods=['GET'])
def report():
return render_template('report.html')
执行某个testsuite后会跳转到报告页面
完整代码:api_test_framework
更多学习资料请加添加作者微信:lockingfree获取
使用Flask搭建基于unittest的简单用例挑选及执行平台的更多相关文章
- 基于Spring-SpringMVC-Mybatis的简单样例
复习下 好久没搞过撸过代码了! 这个样例包括一个完整的增删改查! 源代码地址http://download.csdn.net/detail/wangdianyong/8909903
- 树莓派搭建基于flask的web服务器-通过移动端控制LED
1.概述 在局域网内,基于flask搭建web服务,从而可以使用移动客户端访问该web服务.由于是flask新手,所以本次实现的web服务功能较为简单,即控制LED灯的开/关及闪烁. 2.准备工作 2 ...
- 从零开始用 Flask 搭建一个网站(一)
前言 笔者之前未接触过 Python,只是略懂一点前端,所以说从零开始也相差无几吧.Flask 是一个轻量级的基于 Python 的框架,但是扩展性非常良好(Github 上 22000 多个 sta ...
- 用pymysql和Flask搭建后端,响应前端POST和GET请求
前言 这次作业不仅需要我建立一个数据库(详情请点击这里),还需要我基于这个数据库写后端接口(注册和登录)供前端访问,接收前端的POST和GET请求,并将登录.注册是否成功传给前端. 本文介绍如何用Fl ...
- 面向服务体系架构(SOA)和数据仓库(DW)的思考基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台
面向服务体系架构(SOA)和数据仓库(DW)的思考 基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台 当前业界对面向服务体系架构(SOA)和数据仓库(Data Warehouse, ...
- 象写程序一样写博客:搭建基于github的博客
象写程序一样写博客:搭建基于github的博客 前言 github 真是无所不能.其 Pages 功能 支持上传 html,并且在页面中显示.于是有好事者做了一个基于 github 的博客管理工具 ...
- Windows 7下 搭建 基于 ssh 的sftp 服务器
Windows xp 下 搭建 基于 ssh 的sftp 服务器,服务器端可以用 freesshd,F-secure server等,filezilla server不可用,之前傻乎乎的用file ...
- 从零开始用 Flask 搭建一个网站(三)
从零开始用 Flask 搭建一个网站(二) 介绍了有关于数据库的运用,接下来我们在完善一下数据在前端以及前端到后端之间的交互.本节涉及到前端,因此也会讲解一下 jinja2 模板.jQuery.aja ...
- .net项目架构改造之搭建基于java环境配置一览【上】
最近公司做了一个项目,需要嵌套在千牛的客户端上,项目代码必须上阿里的聚石塔,全程采用基于docker的自动化部署,我们的项目是基于.net架构.很遗憾 的是基于windows的docker上部署在访问 ...
随机推荐
- Python 闭包、迭代器、生成器、装饰器
Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...
- S03_CH04_AXI_DMA_OV5640摄像头采集系统
S03_CH04_AXI_DMA_OV5640摄像头采集系统 4.1概述 本课程讲解如何搭建基于DMA的图形系统,方案原理和搭建7725的一样,只是OV5640显示的分辨率是1280X720如下,只是 ...
- 贝叶斯优化 Bayesian Optimization
贝叶斯优化 Bayesian Optimization 2018年07月02日 22:28:06 余生最年轻 阅读数 4821更多 分类专栏: 机器学习 版权声明:本文为博主原创文章,遵循CC 4 ...
- golang代码中生成pprof和trace报告
// 生成 CPU 报告 import ( "context" "runtime/pprof" "log" ) func cpuProfil ...
- sqlserver查询数据的所有表名和行数及空间占用量
//查询所有表名 select name from sysobjects where xtype='u' --modify_date指表结构最后更新日期,并非数据最后更新日期SELECT na ...
- C#添加带验证的websevice接口
记录一下,方便下次使用,或者能帮助到别人. 一.添加服务引用,输入WSDL文件地址. 二.代码 public TESTClient TestContext() { var binding = new ...
- 基于SDP的提议/应答(offer/answer)模型简介
1.引入 在松耦合会议中,会话参数完全由会议创建者来确定,参与者能做的仅仅是根据这些会话参数来加入会议(当然也可以选择不加入).这种情况下,主要要做的就是会话描述,在这里SDP本身就足够了. 但是在更 ...
- Linux学习(三)-Vi和Vim的区别
它们都是多模式编辑器,不同的是vim 是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面.vim的这些优势主要体现在以下几个方面:1.多级撤消我们知道在vi里,按 u只能撤消上次命 ...
- ASE19团队项目alpha阶段model组 scrum5 记录
本次会议于11月7日,19时整在微软北京西二号楼sky garden召开,持续12分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...
- 第一章、接口规范之Restful规范
阅读目录 2.1 数据的安全保障 2.2 接口特征表现 2.3 多数据版本共存 2.4 数据即是资源 2.5 资源操作由请求方式决定 3.1 正常响应 3.2 重定向响应 3.3 客户端异常 3.4 ...