測開之路六十一:接口測試平臺之interface藍圖

 

create的jscss

//添加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/html

// 畫圖函數,數據動態傳入
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 %}

藍圖的視圖json

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藍圖的處理邏輯flask

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)
相關文章
相關標籤/搜索