這一節我們實現下面兩個功能
- 自動判斷服務器響應的狀態碼,如果狀態碼是4xx,5xx的話則認為請求失敗
- 增加斷言功能,可以判斷響應的json字符串里是否包含預期的字段
為了測試方便,我們先在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])
- /api接口返回json字符串
{"name": "etf", "version": "0.01"}
- /error接口隨機拋出401, 403, 404, 500錯誤中的1個
實現狀態碼自動判斷
再修改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的字典對象,我們可以使用下面的語法來進行斷言
- obj['name'] == 'tfl'
- obj['key'] == 'value'
- obj['key1']['key2'] == 'value1'
也就是提供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 %}
判斷斷言執行的狀態並給予相應的顯示。
完整代碼請點擊這里
總結
- 狀態碼只要大於等於400我們就可以認為請求失敗,大家可以去搜索一下為什么這樣子?
- 使用eval()動態執行代碼非常危險,因為用戶可以輸入任意代碼,嚴重情況下這些代碼可能導致你的服務器被黑客攻陷,所以在生產環境一定不要使用該方法。
- 永遠不要相信用戶輸入,上面的代碼只是演示,並沒有什么實用價值。