这一节我们实现下面两个功能

为了测试方便,我们先在 main.py 文件中增加 2 个测试的接口

@app.route('/api')
def api():
    return jsonify({'name': 'etf', 'version': '0.01'})

@app.route('/error')
def error():
    codes = [404, 401, 403, 500]
    random.shuffle(codes)
    abort(codes[0])

实现状态码自动判断

再修改 handle_get() 方法

def handle_get():
    url = request.form['url']
    try:
        r = requests.get(url)
    except Exception as e:
        print(e)
        r = None

    resp = build_resp(r)

    return render_template('home.html', resp=resp)

def build_resp(r):
    resp = {'success': False}
    if r is None:
        return resp

    if r.status_code < 400:
        resp['success'] = True

    resp['url'] = r.url
    resp['text'] = r.text
    resp['headers'] = r.headers
    resp['status_code'] = r.status_code

    return resp

这里我们新增了 build_resp(r) 方法,该方法的主要作用是判断请求响应的状态码,如果小于 400 就将请求成功状态设置为 True。

下面修改前端页面 home.html

<div class="container">
  <h3 class="text text-center main-title">ETF接口测试平台</h3>
  <form action="/handle_get" method="post">
    <div class="form-group">
      {% if resp and resp['url'] %}
      <input type="text" name="url" id="url" placeholder="请输入URL" class="form-control" autofocus value="{{resp['url']}}">
      {% else %}
        <input type="text" name="url" id="url" placeholder="请输入URL" class="form-control" autofocus>
      {% endif %}
    </div>
    <div class="form-group">
      <input type="submit" name="submit" value="确定" class="btn btn-primary">
    </div>
  </form>
  <hr>

  {% if resp['success'] %}
    <p>接口地址: {{resp['url']}}</p>
    <p>状态码: {{resp['status_code']}}</p>
    <hr>
    <p>Headers</p>
    {% for key, value in resp['headers'].items() %}
      <p> <pre><code>{{key}}: {{value}}</code></pre> </p>
    {% endfor %}

    <hr>
    <p>Body</p>
    <pre>
      <code>
        {{resp['text']}}
      </code>
    </pre>
  {% else %}
    <p class="text text-danger">执行失败</p>
    <p class="text text-danger">状态码: {{resp['status_code']}}</p>
    <p class="text text-danger">响应: {{resp['text']}}</p>
  {% endif%}
</div>

上面主要的修改是回显 get 请求的 url,另外如果请求是失败状态,就展示失败的信息。

修改完成后,使用/error 接口进行测试,效果如下

实现断言

我们使用最偷懒最不安全的方式去实现断言,使用 python 的 eval() 方法,大家有兴趣可以自行了解一下。该方法主要的作用就是动态去执行一段 python 代码,是黑魔法,不安全,仅仅作为演示使用,大家不要在生产环境使用。

我们的设计是让用户在页面上输入一个断言表达式,也就是纯 python 代码。默认情况下我们将服务器返回的 json 字符串转换成 python 字典,并赋值给 obj 变量。简单理解的话就是服务器的返回会自动转成名为 obj 的字典对象,我们可以使用下面的语法来进行断言

也就是提供 1 个 python 表达式,只要表达式返回的是 boolean 值就好了。

实现后效果如下,我们使用/api 接口进行测试

上面我们测试了断言通过和失败的情况,一切如预期。

main.py 中实现的核心代码其实很简单。

def handle_get():
    url = request.form['url']
    assertion = request.form['assert']
    assertion_success = None
    try:
        r = requests.get(url)
        if assertion is not None and assertion != '':
            obj = r.json()
            if assertion:
                assertion_success = eval(assertion)
    except Exception as e:
        print(e)
        r = None

    resp = build_resp(r)
    resp['assertion'] = assertion
    resp['assertion_success'] = assertion_success

    return render_template('home.html', resp=resp)

上面的代码里我们将用户输入的 python 表达式直接使用 eval 方法执行,如果表达式为真,则断言通过,否则失败。该方法很危险,大家可以去搜索一下为什么。

前端页面的核心修改如下

{% if resp['assertion_success'] is not none %}
  {% if resp['assertion_success'] %}
    <p><strong class="text text-success">断言成功</strong></p>
  {% else %}
    <p><strong class="text text-danger">断言失败</strong></p>
  {% endif %}
  <p><code>{{resp['assertion']}}</code></p>
  <hr>
{% endif %}

判断断言执行的状态并给予相应的显示。

完整代码请点击这里

总结


↙↙↙阅读原文可查看相关链接,并与作者交流