create的js

//添加header的函数
function add_header() {
// 这里是动态拼接html语句,带着样式,拼凑成页面的 "key [] value []"
var html = '<div class="row">' +
'<div style="display: inline; width: 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>key</div>' +
'<div style="display: inline; width: 40%; margin-left: 10px; margin-right: 10px;" col-sm--4 col-md-4 col-lg-4><input class="h_key"></div>' +
'<div style="display: inline; width: 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>value</div>' +
'<div style="display: inline; width: 40%; margin-left: 10px; margin-right: 10px;" col-sm--4 col-md-4 col-lg-4><input class="h_value"></div>' +
'</div>'
$('#h_section').append(html); //把html代码加到id为h_section的元素下面
$('#h_section').show(); //展示此元素及刚刚加入的html代码
$('#c_section').show();
} //添加param的函数
function add_param() {
// 这里是动态拼接html语句,带着样式,拼凑成页面的 "key [] value []"
var html = '<div class="row">' +
'<div style="display: inline; width: 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>key</div>' +
'<div style="display: inline; width: 40%; margin-left: 10px; margin-right: 10px;" col-sm--4 col-md-4 col-lg-4><input class="p_key"></div>' +
'<div style="display: inline; width: 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>value</div>' +
'<div style="display: inline; width: 40%; margin-left: 10px; margin-right: 10px;" col-sm--4 col-md-4 col-lg-4><input class="p_value"></div>' +
'</div>'
$('#p_section').append(html); //把html代码加到id为p_section的元素下面
$('#p_section').show(); //展示此元素及刚刚加入的html代码
$('#c_section').show();
} //添加assert的函数
function add_assert() {
// 这里是动态拼接html语句,带着样式,拼凑成页面的 "jsonpath [] expect []"
var html = '<div class="row">' +
'<div style="display: inline; width: 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>jsonpath</div>' +
'<div style="display: inline; width: 40%; margin-left: 10px; margin-right: 10px;" col-sm--4 col-md-4 col-lg-4><input class="a_key"></div>' +
'<div style="display: inline; width: 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>expect</div>' +
'<div style="display: inline; width: 40%; margin-left: 10px; margin-right: 10px;" col-sm--4 col-md-4 col-lg-4><input class="a_value"></div>' +
'</div>'
$('#a_section').append(html); //把html代码加到id为a_section的元素下面
$('#a_section').show(); //展示此元素及刚刚加入的html代码
$('#c_section').show();
} //提取参数
function get_parameter() { //从页面上取需要的数据
var data = {
'method': $("#method").val(),
'host': $("#host").val(),
'header': {},
'params': {},
'assert': []
} // 使用each函数遍历每一个header的key,按照each函数的索引
$('.h_key').each(function (index, element) {
// 分别取出header的key和value
var key = $('.h_key').eq(index).val();
var value = $('.h_value').eq(index).val();
data['header'][key] = value; //保存在data['header']
}) // 使用each函数遍历每一个parameter的key,按照each函数的索引
$('.p_key').each(function (index, element) {
// 分别取出parameter的key和value
var key = $('.p_key').eq(index).val();
var value = $('.p_value').eq(index).val();
data['params'][key] = value; //保存在data['param']
}) // jsonpath是断言的表达式,jsonpath结果与expect匹配,如果符合预期则成功,否则判定为失败。
// 使用each函数遍历每一个assert的jsonpath,按照each函数的索引
$('.a_key').each(function (index, element) {
//分别取出assert的jsonpath作为key和expect作为value
var key = $('.a_key').eq(index).val();
var value = $('.a_value').eq(index).val();
//保存在data['assert'],定义rule为key,expect为value
data['assert'].push({
'rule': key,
'expect': value
})
})
return data; //返回拿到的所有数据
} //debug成功的处理函数
function debug_success(data) {
console.log(data);
// 先清空右侧的响应数据,否则append函数会不断累加结果。
$('#response').empty()
// 将返回的结果append到response区域,代码和json数据显示需要用pre与code标签,json.stringify使用参数null, 4缩进4个空格。
$('#response').append('<pre><code>' + JSON.stringify(data['data'], null, 4) + '</code></pre>')
alert(data['message']) //弹框提示后端返回的message信息
} //debug事件处理函数
function send_request() {
// 这里要注意请求需要加蓝图的url_prefix即/interface
var url = host + '/interface/api/v1/debug';
var data = get_parameter();
http(url, data, 'POST', debug_success, fail); //请求后台的debug接口
} //失败时同一处理,在console里面打印信息
function fail(data) {
console.log(data);
} //保存成功的函数,弹框展示case_id
function save_success(data) {
console.log(data);
alert("保存用例成功,case_id" + data['data'])
} //save事件处理函数
function save_request() {
// 这里要注意请求需要加蓝图的url_prefix即/interface
var url = host + '/interface/api/v1/save'; //请求后台的save接口
var data = get_parameter();
http(url, data, 'POST', save_success, fail);
} //js入口
$(function () {
//初始化时隐藏指定id对应的元素
$('#h_section').hide();
$('#p_section').hide();
$('#a_section').hide();
$('#c_section').hide(); //指定id被点击时,调用对应的处理事件
$('#header').click(add_header);
$('#param').click(add_param);
$('#assert').click(add_assert);
$('#debug').click(send_request);
$('#save').click(save_request);
});

report的js,这里使用百度的echarts:https://echarts.baidu.com/examples/

// 画图函数,数据动态传入
function drawPie(id, data) { var myChart = echarts.init(document.getElementById(id)); var option = {
backgroundColor: '#F5F5F5', //背景色
title: {
text: '测试统计数据',
x: 'center'
}, legend: {
orient: 'vertical',
x: 'left',
data: ['成功', '失败', '未检验']
}, color: ['#3c763d', '#a94442', '#0099CC'], calculable: true, series: [{
name: '测试结果',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
startAngle: 135,
data: [
{
value: data[0],
name: '成功',
itemStyle: {
normal: {
label: {
formatter: '{b} : {c} ({d}%)',
textStyle: {
align: 'left',
fontSize: 15,
}
},
labelLine: {
length: 40,
}
}
}
},
{
value: data[1],
name: '失败',
itemStyle: {
normal: {
label: {
formatter: '{b} : {c} ({d}%)',
textStyle: {
align: 'right',
fontSize: 15,
}
},
labelLine: {
length: 40,
}
}
}
},
{
value: data[2],
name: '未检验',
itemStyle: {
normal: {
label: {
formatter: '{b} : {c} ({d}%)',
textStyle: {
align: 'right',
fontSize: 15,
}
},
labelLine: {
length: 40,
}
}
}
}],
}]
}; // 为echarts对象加载数据
myChart.setOption(option);
} function generate_table_detail(data, id) {
// 拼接table详细测试数据
var html = "";
for (var i = 0; i < data.length; i++) {
var slice = '<tr class="all">' +
'<td class="text-center">' + data[i]['_id'] + '</td>' +
'<td class="text-center">' + data[i]['host'] + '</td>' +
'<td class="text-center">' + data[i]['method'] + '</td>' +
'<td class="text-center">' + data[i]['status'] + '</td>' +
'<td class="text-center">' + data[i]['message'] + '</td>' +
'</tr>'
html = html + slice;
}
$('#' + id).append(html);
} //成功的回调函数,由于后端返回的数据是list(result),所以这里取0的下标
function success(data) {
console.log(data)
var data = data['data']; //从返回数据中取出'data'的数据
$('#start').text(data[0]['time']['start']);
$('#end').text(data[0]['time']['end']);
$('#spend').text(data[0]['time']['cost']);
$('#total').text(data[0]['count']['total']);
$('#run').text(data[0]['count']['run']);
$('#skip').text(data[0]['count']['skip']);
//把数据传给前面写的drawPie()函数(画图函数)
drawPie('pie', [data[0]['count']['success'], data[0]['count']['fail'], data[0]['count']['skip']]); $('#t-total').html(data[0]['count']['total']);
$('#t-success').html(data[0]['count']['success']);
$('#t-fail').html(data[0]['count']['fail']);
$('#t-skip').html(data[0]['count']['skip']); // 筛选成功与失败的数据,还有跳过的数据
total = data[0]['result'];
success = [];
fail = [];
skip = []; console.log(total)
for (var i = 0; i < total.length; i++) {
console.log(total[i]['message']);
if (total[i]['status'] == 0) {
success.push(total[i])
} else {
fail.push(total[i])
}
} //分四次分别处理测试概要信息
generate_table_detail(total, 'panel-data-0');
generate_table_detail(success, 'panel-data-1');
generate_table_detail(fail, 'panel-data-2');
generate_table_detail(skip, 'panel-data-3');
} //失败的回调函数
function fail(data) {
console.log(data)
} // 入口函数
$(function () {
// 请求后端返回测试报告
// 测试报告通过url的最后一个字段(run_id)去取
var url = host + '/interface/api/v1/report'; //
var uri = window.location.href; //浏览器上的url
var slice = uri.split("/"); //把url根据/切割
var data = {
'id': slice[slice.length - 1] //拿切割后的最后一个数据,就是传进来的runid
};
http(url, data, 'POST', success, fail); //把runid发到后端处理
});

create的html

<!- 继承base ->
{% extends 'base.html' %} <!- 声明需要的js ->
{% block script %}
<script src="/interface/static/create.js"></script>
{% endblock %} <!- 页面内容 ->
{% block content %} <!- 声明一个描点作为bootstrap容器 ->
<div class="container"> <!- 声明整个页面内容页为一行 ->
<div class="row"> <!- 将一行分为12列,左右各占6份,即均分为各占6份的两大列 ->
<div class="col-sm-12 col-md-6 col-lg-6"> <!- 声明左侧列请求方法的下拉框、url的输入框、增加header参数、param参数、断言参数的按钮为1行 ->
<div class="row">
<!- 选择请求方法的下拉框 ->
<select id="method">
<option value="get">get</option>
<option value="post">post</option>
<option value="put">put</option>
<option value="delete">delete</option>
</select>
<!- url的输入框、增加header参数、param参数、断言参数的按钮 ->
<input id="host" type="text" placeholder="http://www.baidu.cn">
<input id="header" type="button" value="header">
<input id="param" type="button" value="param">
<input id="assert" type="button" value="assert">
</div> <!- 预留一个描点给后面js加header参数用,并且单独为一行 ->
<div id="h_section" class="row">
<hr>
<label>请求头</label>
</div> <!- 预留一个描点给后面js加params参数用,并且单独为一行 ->
<div id="p_section" class="row">
<hr>
<label>请求参数</label>
</div> <!- 预留一个描点给后面js加assert参数用,并且单独为一行 ->
<div id="a_section" class="row">
<hr>
<label>添加断言</label>
</div> <!- 预留一个描点给后面js触发debug和save事件,并且声明这两个按钮为一行 ->
<div id="c_section" class="row">
<hr>
<input id="debug" type="button" value="debug">
<input id="save" type="button" value="save">
<hr>
</div>
</div> <!- 右边大列(6小列),用于展示响应数据 ->
<div class="col-sm-12 col-md-6 col-lg-6">
<div id="response"></div>
</div>
</div>
</div>
{% endblock %}

report的html

{% extends 'base.html' %} <!- 继承base.html ->

{% block style %}
<style type="text/css" media="screen">
body {
margin: 0;
font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", sans-serif;
font-size: 18px;
line-height: 1.5;
line-height: 1.5;
color: #333333;
} .table {
margin-bottom: 1px;
width: 100%;
} .hiddenRow {
display: none;
} .container-fluid {
padding-right: 120px;
padding-left: 120px;
} .nav-tabs li {
width: 186px;
text-align: center;
}
</style>
{% endblock %} {% block script %}
<!- 从cdn引入echarts的js、interface蓝图下report的js ->
<script src="https://cdn.bootcss.com/echarts/4.1.0-release/echarts.min.js"></script>
<script src="/interface/static/report.js"></script>
<!- 展示测试结果详细信息 ->
<script>
function showClassDetail(detail_id, hiddenRow_id, class_type) {
console.log(document.getElementById(hiddenRow_id).className) if ('详细' == document.getElementById(detail_id).innerText) {
if ('all' == class_type) {
document.getElementById(hiddenRow_id).className = 'all';
} else if ('success' == class_type) {
document.getElementById(hiddenRow_id).className = 'success';
} else if ('error' == class_type) {
document.getElementById(hiddenRow_id).className = 'error';
} else {
document.getElementById(hiddenRow_id).className = 'untreaded';
}
document.getElementById(detail_id).innerText = "收起"
} else {
document.getElementById(detail_id).innerText = "详细"
document.getElementById(hiddenRow_id).className = 'hiddenRow';
}
}
</script>
{% endblock %} {% block content %}
<div class="page-header">
<h1 class="text-primary" style="font-size:45px;line-height:75px">testfan测试报告</h1>
</div> <div class="col-md-12">
<div class="col-md-4" style="Background-Color:#F5F5F5; height:300px">
<h3 style="line-height:25px">测试基本信息</h3>
<table class="table table-hover table-bordered" style="width:100%;height:11px">
<tbody>
<tr class="info">
<td class="text-center">开始时间</td>
<td id="start" class="text-center"></td>
</tr>
<tr class="info">
<td class="text-center">结束时间</td>
<td id="end" class="text-center"></td>
</tr>
<tr class="info">
<td class="text-center">测试用时</td>
<td id="spend" class="text-center"></td>
</tr>
<tr class="info">
<td class="text-center">总用例数</td>
<td id="total" class="text-center"></td>
</tr>
<tr class="info">
<td class="text-center">执行用例数</td>
<td id="run" class="text-center"></td>
</tr>
<tr class="info">
<td class="text-center">跳过用例数</td>
<td id="skip" class="text-center"></td>
</tr>
</tbody>
</table>
</div> <div class="col-md-8">
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="pie" style="height:300px;"></div>
</div>
</div>
<div>
<div><span>&nbsp;</span></div>
<div class="col-md-12">
<div class="tabbable" id="tabs-957640">
<ul class="nav nav-tabs">
<li class="active">
<a href="#panel-0" data-toggle="tab" style="Background-Color: #428bca; color: #fff;">全 部 (<label
id="t-total"></label>)</a>
</li>
<li>
<a href="#panel-1" data-toggle="tab" style="Background-Color: #5cb85c; color: #fff;">成 功 (<label
id="t-success"></label>)</a>
</li>
<li>
<a href="#panel-2" data-toggle="tab" style="Background-Color: #d9534f; color: #fff;">失 败 (<label
id="t-fail"></label>)</a>
</li>
<li>
<a href="#panel-3" data-toggle="tab" style="Background-Color: #5bc0de; color: #fff;">未验证 (<label
id="t-skip"></label>)</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="tab-pane active" id="panel-0">
<table class="table table-hover table-bordered">
<tbody id="panel-data-0">
<tr class="all">
<td class="text-center" style="Background-Color:#dff0d8">用例编号</td>
<td class="text-center" style="Background-Color:#dff0d8">测试域名</td>
<td class="text-center" style="Background-Color:#dff0d8">接口方法</td>
<td class="text-center" style="Background-Color:#dff0d8">测试状态</td>
<td class="text-center" style="Background-Color:#dff0d8">测试结果</td>
</tr>
</tbody>
</table>
</div> <div class="tab-pane" id="panel-1">
<table class="table table-hover table-bordered">
<tbody id="panel-data-1">
<tr class="all">
<td class="text-center" style="Background-Color:#dff0d8">用例编号</td>
<td class="text-center" style="Background-Color:#dff0d8">测试域名</td>
<td class="text-center" style="Background-Color:#dff0d8">接口方法</td>
<td class="text-center" style="Background-Color:#dff0d8">测试状态</td>
<td class="text-center" style="Background-Color:#dff0d8">测试结果</td>
</tr>
</tbody>
</table>
</div> <div class="tab-pane" id="panel-2">
<table class="table table-hover table-bordered">
<tbody id="panel-data-2">
<tr class="all">
<td class="text-center" style="Background-Color:#dff0d8">用例编号</td>
<td class="text-center" style="Background-Color:#dff0d8">测试域名</td>
<td class="text-center" style="Background-Color:#dff0d8">接口方法</td>
<td class="text-center" style="Background-Color:#dff0d8">测试状态</td>
<td class="text-center" style="Background-Color:#dff0d8">测试结果</td>
</tr>
</tbody>
</table>
</div> <div class="tab-pane" id="panel-3">
<table class="table table-hover table-bordered">
<tbody id="panel-data-3">
<tr class="all">
<td class="text-center" style="Background-Color:#dff0d8">用例编号</td>
<td class="text-center" style="Background-Color:#dff0d8">测试域名</td>
<td class="text-center" style="Background-Color:#dff0d8">接口方法</td>
<td class="text-center" style="Background-Color:#dff0d8">测试状态</td>
<td class="text-center" style="Background-Color:#dff0d8">测试结果</td>
</tr>
</tbody>
</table>
</div>
</div>
</div> </div>
</div> {% endblock %}

蓝图的视图

from flask import request
from flask import jsonify
from flask import Blueprint
from flask import render_template
from interface.logic import Logic """ 接口测试蓝图 """
interface = Blueprint('interface', __name__,
static_folder='static', # interface蓝图的静态文件
template_folder='templates', # interface的模板
url_prefix='/interface') # interface的路由,host:port/interface/+... @interface.route('create')
def create():
""" 创建接口测试页面的路由 """
return render_template("create.html") @interface.route('/api/v1/debug', methods=['POST'])
def api_v1_debug():
""" debug接口处理视图 """
# get请求使用request.values.to_dict接收,post、put、delete使用request.get_json接收
data = request.get_json() # 判断有没有传method参数
method = data.get('method', None)
if not method:
return jsonify({
'status': 400,
'message': 'method参数必传',
'data': data,
}) # 判断有没有传host参数
host = data.get('host', None)
if not host:
return jsonify({
'status': 400,
'message': 'host参数必传',
'data': data,
}) # 处理逻辑
try:
status, message, data = Logic().execute(data)
return jsonify({
'status': status,
'message': message,
'data': data,
})
except Exception as error:
return jsonify({
'status': 500,
'message': str(error),
'data': data
}) @interface.route('/api/v1/save', methods=['POST'])
def api_v1_save():
""" 保存接口处理视图 """
data = request.get_json()
# 定义错误的返回内容
fail = {
'status': 400,
'data': data,
}
# 校验method必传
method = data.get('method', None)
if not method:
fail.setdefault('message', 'method参数必传')
return jsonify(fail) # 校验host必传
host = data.get('host', None)
if not host:
fail.setdefault('message', 'host参数必传')
return jsonify(fail) # 执行保存逻辑,保存成功就返回id,否则就返回接收的内容
try:
ids = Logic().save(data)
return jsonify({
'status': 0,
'message': 'success',
'data': ids,
})
except Exception as error:
return jsonify({
'status': 500,
'message': str(error),
'data': data
}) @interface.route('report/<id>')
def report(id):
""" 访问时为report/runid """
return render_template("report.html") @interface.route('/api/v1/trigger', methods=['POST'])
def api_v1_trigger():
""" 触发运行用例接口 """
data = request.values.to_dict() # 接收参数(这里前端传字典格式) ids = data.get('id', None) # 拿前端传过来的id
if not ids: # 没有传id就返回400
return jsonify({
'status': 400,
'message': 'id必传',
'data': data,
}) # 执行触发运行
try:
result = Logic().trigger(data)
return jsonify({
'status': 0,
'message': 'success',
'data': result,
})
except Exception as error:
return jsonify({
'status': 500,
'message': str(error),
'data': data
}) @interface.route("/api/v1/report", methods=['POST'])
def api_v1_report():
""" 根据runid查测试据结果数据 """
data = request.get_json()
print(data)
id = data.get('id', None)
if not id:
return jsonify({
'status': 400,
'message': 'invalid parameter [id]',
'data': data,
}) try:
report = Logic().report(data)
return jsonify({
'status': 0,
'message': 'success',
'data': report,
})
except Exception as error:
return jsonify({
'status': 500,
'message': str(error),
'data': data
})

interface蓝图的处理逻辑

import time
import requests
from jsonpath import jsonpath
from common.mongo import Mongo
from common import get_case_id
from common import get_timestamp """ 功能处理逻辑 """ class Logic(object):
JSONPATH_ASSERT_SUCCESS = 0 # jsonpath断言通过
HTTP_REQUEST_FAIL = 1 # 请求失败
JSONPATH_ASSERT_FAIL = 2 # 断言不通过
JSONPATH_EXECUTE_FAIL = 3 # jsonpath取值失败
RESPONSE_DATA_FORMAT_ERROR = 4 # 相应数据格式错误 def __init__(self):
self.db = Mongo() def execute(self, data):
""" 用前端传过来的数据发送http请求,返回值为元组,分别是flag,message和接口请求后的json数据 """
# 拿对应数据
method = data.get("method")
host = data.get("host")
header = data.get('header', {})
payload = data.get('params', {}) # 发送http请求
if method == 'get':
response = requests.request(method, host, params=payload, headers=header)
else:
response = requests.request(method, host, data=payload, headers=header) # 解析响应结果
try:
json = response.json()
except Exception:
flag = Logic.RESPONSE_DATA_FORMAT_ERROR
message = "响应数据非json"
return flag, message, {} # 执行断言
# 初始化flag为JSONPATH_ASSERT_SUCCESS,message为测试成功
flag = Logic.JSONPATH_ASSERT_SUCCESS
message = "测试通过" # 如果响应状态码不是200,则视请求接口失败
if response.status_code != 200:
flag = Logic.HTTP_REQUEST_FAIL
message = "请求接口失败!"
return flag, message, json # 解析assert数据
items = data.get('assert', [])
# 把assert数据里的每一个rule(预期结果,jsonpath表达式)拿出来取数据
for item in items:
result = jsonpath(json, item['rule'])
# 如果返回的result没有值,则说明取值失败
if not result:
flag = Logic.JSONPATH_EXECUTE_FAIL
message = "jsonpath取值失败"
break
# 把所有预期结果分别转成str,再转为list
result = list(map(str, result))
# 判断两个list(预期结果和实际结果)是否相等['1', '2'] != ['1', '2']
if result != [item['expect']]:
flag = Logic.JSONPATH_ASSERT_FAIL
message = "测试断言不通过"
break
return flag, message, json # 根据断言状态返回状态码和信息 def save(self, data):
""" 保存用例的逻辑 """
print(data)
data.setdefault('_id', get_case_id()) # 把_id的值重新赋值为自定义的caseid
# 把数据保存到2019库里的interface表
ids = self.db.insert("2019", "interface", data) # 数据库层已经定义好了save完后返回自定义的caseid
return ids # 这里把拿到的id直接返回 def trigger(self, data):
""" 根据接收到的caseid触发运行case """
cases = []
# 前端传递过来的是一组用逗号分隔的ID,用ID去数据库里查找用例。
# 如果能查找到则放入cases里待后面去运行。
id_list = data.get('id').split(',') # 把所有的id分割为一个list
# 根据拿到的id去查caseid
for case_id in id_list:
results = self.db.search("2019", "interface", {'_id': case_id})
# 如果取出来的caseid有值,就加到cases里面
if not results:
continue
for result in results:
cases.append(result) # 初始化测试结果数据,这个data是要存储到数据库的测试报告数据。
data = {
'_id': get_case_id(), # 定义run_id(运行id)
'time': { # 统计时间
'start': 0,
'end': 0,
'cost': 0,
},
'count': { # 统计用例执行相关的个数
'total': 0,
'run': 0,
'success': 0,
'fail': 0,
'skip': 0
},
'result': [] # 执行结果
} start = time.time() # 开始运行时间
# 判断每一个测试用例是否通过。
for case in cases:
data['count']['total'] += 1 # 用例总数+1
data['count']['run'] += 1 # 执行数+1
status, message, _ = self.execute(case) # 执行并接收返回数据
if status == 0: # 判断返回状态 ,前面已经定义0位成功,1/2/3/4都是各种失败
data['count']['success'] += 1 # 成功数+1
else:
data['count']['fail'] += 1 # 失败数+1
# 更新case执行的状态和执行信息
case['status'] = status
case['message'] = message
data['result'].append(case) # 把更新状态后的case加到reslut里面
print("{0} {1} {2} {3}".format(data['count']['total'], data['count']['run'],
data['count']['success'], data['count']['fail']))
end = time.time() # 结束运行时间
# 通过start与end时间戳计算整个测试耗时
data['time']['start'] = get_timestamp(start) # 开始时间,字符串格式
data['time']['end'] = get_timestamp(end) # 结束时间,字符串格式
data['time']['cost'] = "共执行{0:0.3}秒".format(end - start) # 执行用的时间,保留3位小数
# 将测试报告数据写入数据库。
self.db.insert('2019', 'report', data)
return data['_id'] # 返回本次的run_id def report(self, data):
""" 根据接收的runid查测试结果数据,用于生成html报告 """
run_id = data.get('id')
result = self.db.search("2019", "report", {'_id': run_id}) # 存到2019库的report表里面
return list(result)

测开之路六十一:接口测试平台之interface蓝图的更多相关文章

  1. 测开之路六十:接口测试平台之common目录

    实现接口测试平台使用jsonpath进行取值来断言,效果: 访问页面: 调试功能:http://www.kuaidi100.com/query 保存功能 触发执行功能 查看报告功能 目录结构 comm ...

  2. 测开之路六十二:接口测试平台之公共的js、html、平台入口

    common.js //定义后台的host和端口var host = 'http://192.168.xxx.1:8000'; //'http://127.0.0.1:8000'; //用于发送htt ...

  3. 测开之路七十一:监控平台之js

    监控平台的js //datetimepicker的初始化函数(主要是对选择时间的下拉框)function init_datetimepicker() { //初始化格式和规则 $('#start'). ...

  4. 测开之路六十六:UI测试平台之处理逻辑和蓝图添加到程序入口

    from selenium import webdriverfrom common import get_case_idfrom common.mongo import Mongo class Log ...

  5. 测开之路六十五:UI测试平台之js

    //添加网址的函数,生成一个输入网址的标签,并且把标签append到id为cases下function browser() { var html = '\ <div class="ro ...

  6. 测开之路六十四:UI测试平台之前端页面

    {% extends "base.html" %} {% block script %} <!-- 引入js文件,需要在base.html留入口,不然渲染会出问题. --&g ...

  7. 测开之路六十三:UI测试平台之视图层

    实现效果,在页面时配置 后台执行 蓝图结构 视图代码 from flask import jsonifyfrom flask import requestfrom flask import Bluep ...

  8. 测开之路九十一:css常用的选择器

    一:全局选择器:* 二:标签选择器,如给所有p标签加个背景色 三:id选择器:# ,如给id为id_01的元素加一个框 四:类选择器:. 如设置一个类选择器为blue,当有标签引用blue的时候,背景 ...

  9. 测开之路八十一:参数定义之*args和**kwargs

    # *,不定长参数,*args# 定义函数参数def avg(score, *scores):    return (score + sum(scores)) / (len(scores) + 1) ...

随机推荐

  1. [Python3] 018 if:我终于从分支中走出来了

    目录 0. 谁是主角 1. 从三大结构说起 (1) 顺序 (2) 分支 1) 分支的基本语法 2) 双向分支 3) 多路分支 (3) 循环 0. 谁是主角 分支是主角 我前面几篇随笔提到 if 不下2 ...

  2. javascript详细介绍

    一.JavaScript基础 1.什么是JavaScript? JavaScript是一种客户端运行的解释性脚本语言. JavaScript是由网景(Netscape)推出的产品. Microsoft ...

  3. Tunnel Warfare HDU 1540 区间合并+最大最小值

    Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里 ...

  4. React手稿之 React-Saga

    Redux-Saga redux-saga 是一个用于管理应用程序副作用(例如异步获取数据,访问浏览器缓存等)的javascript库,它的目标是让副作用管理更容易,执行更高效,测试更简单,处理故障更 ...

  5. 2019 Multi-University Training Contest 2 - 1008 - Harmonious Army - 最大流

    http://acm.hdu.edu.cn/showproblem.php?pid=6598 一开始就觉得是网络流,但是一直都不会怎么建图. 这里要考虑. 每一组边(u,v,a,b,c)建立如下的连接 ...

  6. EOJ Monthly 2019.2 A. 回收卫星

    题目传送门 题意: 你可以询问一个三维坐标,机器会告诉你这个坐标在不在目标圆中, 并且(0,0,0)是一定在圆上的,叫你求出圆心坐标 思路: 因为(0,0,0)一定在圆上,所以我们可以把圆心分成3个坐 ...

  7. HTML5-video(播放暂停视频;打开关闭声音;进度条)

    <!DOCTYPE html> <html> <head> <title>HTML5-video(播放暂停视频:打开关闭声音:进度条)</titl ...

  8. js中JSON和JSONP的区别,让你从懵逼到恍然大悟

    说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...

  9. pg_dump - 将一个PostgreSQL数据库抽出到一个脚本文件或者其它归档文件中

    SYNOPSIS pg_dump [ option...] [ dbname] DESCRIPTION 描述 pg_dump 是一个用于备份 PostgreSQL 数据库的工具.它甚至可以在数据库正在 ...

  10. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) - A

    题目链接:http://codeforces.com/contest/831/problem/A 题意:给定一个序列,问你这个序列是否是单峰的. 定义单峰的序列为: (序列值的变化趋势)开始是递增的, ...