zoukankan      html  css  js  c++  java
  • 测开之路六十一:接口测试平台之interface蓝图

    create的js

    //添加header的函数
    function add_header() {
    // 这里是动态拼接html语句,带着样式,拼凑成页面的 "key [] value []"
    var html = '<div class="row">' +
    '<div style="display: inline; 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>key</div>' +
    '<div style="display: inline; 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; 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>value</div>' +
    '<div style="display: inline; 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; 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>key</div>' +
    '<div style="display: inline; 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; 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>value</div>' +
    '<div style="display: inline; 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; 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>jsonpath</div>' +
    '<div style="display: inline; 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; 10%; margin-left: 10px; margin-right: 10px;" col-sm--2 col-md-2 col-lg-2>expect</div>' +
    '<div style="display: inline; 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;
    100%;
    }

    .hiddenRow {
    display: none;
    }

    .container-fluid {
    padding-right: 120px;
    padding-left: 120px;
    }

    .nav-tabs li {
    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="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)
  • 相关阅读:
    《算法竞赛入门经典》—— 5.2.6 栈、队列与优先队列
    《算法:C语言实现》—— 第二部分 —— 第3章 —— 基本数据结构
    《算法:C语言实现》—— 第二部分 —— 第3章 —— 基本数据结构
    《算法:C语言实现》—— 第二部分 —— 第3章 —— 基本数据结构
    Broken Keyboard (a.k.a. Beiju Text)
    Broken Keyboard (a.k.a. Beiju Text)
    Broken Keyboard (a.k.a. Beiju Text)
    mongodb实战聚合 组内排序
    mongodb实战聚合 组内排序
    MongoDB基础篇:MongoDB Shell命令大全
  • 原文地址:https://www.cnblogs.com/zhongyehai/p/11148691.html
Copyright © 2011-2022 走看看