在用例组织上,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个页面:

  1. 添加用例 suite_add
  2. 用例列表(可以选择suite执行)suite_list
  3. 报告页面 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这个接口的实现逻辑为:

  1. 使用unittest的discover遍历并抽取所有用例返回给客户端(GET请求)
  2. 获取到客户端挑选的用例并生成unittest的TestSuite对象
  3. 根据客户端传的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列表, 思路:

  1. 使用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的简单用例挑选及执行平台的更多相关文章

  1. 基于Spring-SpringMVC-Mybatis的简单样例

    复习下 好久没搞过撸过代码了! 这个样例包括一个完整的增删改查! 源代码地址http://download.csdn.net/detail/wangdianyong/8909903

  2. 树莓派搭建基于flask的web服务器-通过移动端控制LED

    1.概述 在局域网内,基于flask搭建web服务,从而可以使用移动客户端访问该web服务.由于是flask新手,所以本次实现的web服务功能较为简单,即控制LED灯的开/关及闪烁. 2.准备工作 2 ...

  3. 从零开始用 Flask 搭建一个网站(一)

    前言 笔者之前未接触过 Python,只是略懂一点前端,所以说从零开始也相差无几吧.Flask 是一个轻量级的基于 Python 的框架,但是扩展性非常良好(Github 上 22000 多个 sta ...

  4. 用pymysql和Flask搭建后端,响应前端POST和GET请求

    前言 这次作业不仅需要我建立一个数据库(详情请点击这里),还需要我基于这个数据库写后端接口(注册和登录)供前端访问,接收前端的POST和GET请求,并将登录.注册是否成功传给前端. 本文介绍如何用Fl ...

  5. 面向服务体系架构(SOA)和数据仓库(DW)的思考基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台

    面向服务体系架构(SOA)和数据仓库(DW)的思考 基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台 当前业界对面向服务体系架构(SOA)和数据仓库(Data Warehouse, ...

  6. 象写程序一样写博客:搭建基于github的博客

    象写程序一样写博客:搭建基于github的博客   前言 github 真是无所不能.其 Pages 功能 支持上传 html,并且在页面中显示.于是有好事者做了一个基于 github 的博客管理工具 ...

  7. Windows 7下 搭建 基于 ssh 的sftp 服务器

    Windows  xp 下 搭建 基于  ssh 的sftp 服务器,服务器端可以用 freesshd,F-secure server等,filezilla server不可用,之前傻乎乎的用file ...

  8. 从零开始用 Flask 搭建一个网站(三)

    从零开始用 Flask 搭建一个网站(二) 介绍了有关于数据库的运用,接下来我们在完善一下数据在前端以及前端到后端之间的交互.本节涉及到前端,因此也会讲解一下 jinja2 模板.jQuery.aja ...

  9. .net项目架构改造之搭建基于java环境配置一览【上】

    最近公司做了一个项目,需要嵌套在千牛的客户端上,项目代码必须上阿里的聚石塔,全程采用基于docker的自动化部署,我们的项目是基于.net架构.很遗憾 的是基于windows的docker上部署在访问 ...

随机推荐

  1. PowerShell 反弹渗透技巧

    Windows PowerShell 是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用 .NET Framework的强大功能,并且与现有的WSH保持向后兼容,因此它的脚本程序不仅能访 ...

  2. Visual Studio container tools require Docker to be running

    处理项目在生成时报错"Visual Studio container tools require Docker to be running" 最初win10上安装docker,项目 ...

  3. 基于MFC对话框的2048游戏

    在之前一篇<简单数字拼板游戏学习>基础上修改,地址:http://www.cnblogs.com/fwst/p/3706483.html 开发环境:Windows 7/ Visual St ...

  4. B站视频下载

    借助Chrome插件 bilibili哔哩哔哩下载助手 在谷歌应用商城下载安装后在在浏览器右上角显示如下图标 打开想要下载的视频,网页右下角会有如下图标,点击该图标 点击下面的合并下载按钮即可 htt ...

  5. js 扁平化输出数组

    1.使用数组的flat方法 [1,2,[3,[4,5]]].flat(Infinity) //[1, 2, 3, 4, 5] 2.实现方式二: var arr = [[1, 2, 23], [13, ...

  6. 分布式任务队列 Celery —— Task对象

    转载至 JmilkFan_范桂飓:http://blog.csdn.net/jmilk  目录 目录 前文列表 前言 Task 的实例化 任务的名字 任务的绑定 任务的重试 任务的请求上下文 任务的继 ...

  7. Servlet和JSP学习总结

    目录 Jsp会被编译成servlet,在页面被第一次访问的时候 Jsp中可以在html页面中嵌入java代码或者引入jsp标签 可以在html中引入自定义标签 Web工程的目录结构 Jsp的注释 Js ...

  8. python多继承下的查找顺序-MRO原则演变与C3算法

    在python历史版本中的演变史 python2.2之前: MRO原则: 只有经典类,遵循深度优先(从左到右)原则, 存在的问题:在有重叠的多继承中,违背重写可用原则 解决办法是再设计类的时候不要设计 ...

  9. (二十五)防编译后函数名通过ida查看到

    在使用多个动态库时,两个动态库之间有可能存在相同名称的函数,这样会出现只有第一个函数生效,即所有对该函数的调用都将指向第一个加载的动态库的同名函数中.这样就会很混乱,而且在想改名称也不是很简单的情况下 ...

  10. 七:mvc使用CodeFirst(代码优先)创建数据库

    1. 理解EF CodeFirst模式特点 2. 使用CodeFirst模式生成数据库 1. CodeFirst模式(代码优先) Code First是Entity Framework提供的一种新的编 ...