前言
作为开发老司机,有时候会碰到公司研发整体架构流程还不完善的情况。项目接口经常变更,上线比较随意,甚至接口参数变更了都没有人知道,同时又缺少测试。导致线上问题频发,客户投诉反馈了才后知后觉地发现问题,再急忙修复。这时候检测接口可用性就显得很有必要。
老司机当然会先找下云服务上有没有相关类似的产品,云拨测似乎可以解决类似的问题,不得不说云厂商已经覆盖了90%以上的场景。
云拨测(Cloud Automated Testing,CAT)利用分布于全球的监测网络,以真实终端用户使用场景为视角,提供模拟终端用户体验的拨测服务。CAT 可实现对网络质量、页面性能、端口性能、文件传输、音视频体验等场景进行周期性监控,支持多维度分析性能指标。利用可视化性能数据和告警通知可帮助您及时对业务质量作出反应,保证业务稳定正常运行。------ 腾讯云拨测服务介绍
下面是云拨测的价格:
不是,我就想测下接口可用性也要那么贵的吗? 好吧,这事估计害得自己来。
动手
首先,公司的接口一般都是比较复杂的或者带着鉴权的,写代码写起来可能一套下来花费的功夫太多。尽量要避免下写大量代码去实现,不然就得不偿失了。
其次,一些过程实现最好是流行的开源的,标准统一,方便修改,易于维护。
好了,废话不要太多,正式介绍下实现接口可用性检测的方案。
实现方案
整体实现的核心是通过利用 Postman
的功能来完成的(没想到吧,想到的当我没说)。
利用到的各个组件为:
Postman
编写测试用的接口,Postman
能完成的工作相当丰富,检测个接口不在话下。提醒一点,可以在Tests
里面编写需要测试用例,比如你可以验证模拟账号密码登录后,返回的结果是否是成功状态。又或者是在Tests
里面注入一些全局使用的Token
供后续使用。Postman
功能强大,再多的举例就不说了,不再班门弄斧。Newman
下一步,我们需要用命令行去运行Postman
编写好的导出的脚本代码。这里需要用到Node
来安装运行Newman
。最后运行脚本参考:
bash
#!/bin/bash
datetime=$(date "+%Y%m%d%H%M")
filename="/home/wwwroot/default/static/apitest_${datetime}.html"
source /etc/profile && cd /usr/local/lib/node/node-v16.20.2-linux-x64/lib/node_modules/newman/bin/ && /usr/local/lib/node/node-v16.20.2-linux-x64/lib/node_modules/newman/bin/newman.js run /home/wwwroot/script/auto_test_v1.json -r htmlextra,cli --reporter-htmlextra-export "$filename"
Node
使用的是v16版本,Newman
运行结果默认的情况下较为简单,可以通过引入额外的模板让输出结果更容易阅读。这里使用 newman-reporter-htmlextra 模板。当然了,外国人用的就是英文。相信大部分老司机都是中文使用者,如果需要修改模板,找到安装目录下的模板文件 dashboard-template.hbs
狠狠的修改它,参考路径 vi /usr/local/lib/node/node-v16.20.2-linux-x64/lib/node_modules/newman-reporter-htmlextra/lib/dashboard-template.hbs
。
- 利用
gitlab
和jenkins
完成发布功能。 - 利用服务器定时任务进行任务执行。需要注意的是,这里没有过多考虑程序运行时间,超时时间等情况,抛砖引玉,根据实际情况做调整。
- 输出
html
文件,通过nginx
发布浏览。 - 最后的最后,提醒一定是最重要的功能,日常工作中,企业微信是最常用的工具,我们可以利用企业微信完成一个很好的提醒效果。当然也可以更换成邮件或者其他方式。
上参考代码:
python
# encoding=utf-8
import cptools
import re
import sys
import time
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from corpwechatbot.app import AppMsgSender
def read_file(file_path):
try:
with open(file_path, 'r') as file:
content = file.read()
file.close()
return content.replace("\n", "")
except FileNotFoundError:
return ""
except:
return ""
def write_file(file_path, content):
try:
with open(file_path, 'w') as file:
file.write(content)
file.close()
print("写入文件成功")
except:
print("写入文件出错")
if __name__ == "__main__":
now_timestamp = round(time.time())
the_now_time = time.strftime("%Y%m%d%H%M", time.localtime(now_timestamp-60))
request_path = ("http://127.0.0.1/static/apitest_%s.html" % the_now_time)
remind_time_path = "/root/python/apitj/remind_time.log"
is_send = False
if len(sys.argv) > 1 and str(sys.argv[1]) == "1":
is_send = True
last_remind_time = read_file(remind_time_path)
try:
if now_timestamp - int(last_remind_time) < 1800:
print("最后一次提醒时间为%s, 不需要重新提醒" % str(last_remind_time))
exit()
except Exception as e:
print("有异常,需要正常执行")
response = requests.get(request_path)
if response.status_code == 200:
print("Status code is 200")
if "Failed Tests" in response.text:
if (f'Failed Tests <span class="badge badge-light">0</span>' not in response.text) or (is_send is True):
print('screenshot start')
chrome_options = Options()
chrome_options.binary_location = '/usr/bin/google-chrome'
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
driver = webdriver.Chrome(options=chrome_options, executable_path='/usr/local/bin/chromedriver')
driver.set_window_size(1100, 1200)
monitor_img_path = '/root/python/apitj/alert.png'
driver.get(request_path)
time.sleep(3)
# Trigger the desired event
# driver.execute_script('document.getElementById("pills-failed-tab").click();')
# Wait for the event to take effect
# time.sleep(1)
driver.save_screenshot(monitor_img_path)
driver.close()
driver.quit()
print("screenshot end")
the_now_time_format = time.strftime("%m月%d日%H时%M分", time.localtime(now_timestamp))
pattern = r'Failed Tests <span class="badge badge-light">(\d+)</span>'
matches = re.findall(pattern, response.text)
if matches:
failtests = matches[0]
msg = "检查到有%s个失败的测试用例" % failtests
else:
msg = "未检查到有失败的测试用例"
write_file(remind_time_path, str(now_timestamp))
user_list = ["xxx"]
app = AppMsgSender(corpid='xxxxx',
corpsecret='xxxxx',
agentid='xxxxx',
log_level=cptools.INFO)
# app.send_image(image_path=monitor_img_path, touser=user_list)
# app.send_card(title="接口可用性检查", desp="定时对关键接口进行可用性检查", url=request_path, btntxt="报告详情")
app.send_card(title="接口可用性告警",
desp=("<div class=\"gray\">当前时间:%s</div> <div class=\"highlight\">%s</div> "
"<div class=\"normal\">定时对关键接口进行可用性检查</div>" % (the_now_time_format, msg)),
url=request_path, btntxt="报告详情", touser=user_list)
app.send_image(image_path=monitor_img_path, touser=user_list)
else:
print("Status code is not 200")
好了,到此就完成了整个接口可用性检测的整个方案。大家学废了吗?
PS:注意生成的HTML文件别把服务器写满了,记得定期清理。