項目參考文獻:https://testerhome.com/topics/6135
思路:
- 1、讀取禪道數據庫數據及狀態,把各維度統計數據通過dic格式返回
- 2、讀取數據通過pyecharts類,生成不同類型的報表HTML放入image_html文件中
- 3、讀取image_html文件中本次生成的HTML並生成圖片,放入static文件中
- 4、把圖片寫入HTML文件中,因為郵件正文是HTML格式
- 5、文字及圖片HTML文件組合郵件正文,進行發送郵件
- 6、上述功能對外提供服務接口,接口傳參為產品ID及項目ID,調取接口即可自動發送測試報告
主要用到pyecharts,os,flask,pymysql,yagmail等模塊,目前就是初步的小程序,后續再更新一版有界面,可自行選擇產品及項目,查看項目各維度情況報表,另外有些日志和異常處理還沒有完善
目錄結構:
主要代碼:
1、數據庫數據讀取
import pymysql from auto_report.o_util import spread,list_dic from auto_report.setting import db #建立數據庫連接及執行 def connect_db(sql): conn = pymysql.connect( **db,charset='utf8', autocommit=True) cur = conn.cursor() # 建立游標 sql = sql cur.execute(sql) r_result =spread(cur.fetchall()) cur.close() conn.close() return r_result #BUG狀態統計SQL封裝 def sql_pakeage(productid,projectid): bug_sql = "select count(*) from zt_bug where product='%d' and project='%d' and deleted='0'"% ( productid, projectid) resolved_bug_sql = "select count(*) from zt_bug where product = '%d' and project='%d' and deleted = '0' and `status` = 'resolved' and resolution <> 'postponed' " % ( productid, projectid) not_resolved_bug_sql = "select count(*) from zt_bug where product = '%d' and project='%d' and deleted = '0' and `status` = 'active' " % ( productid, projectid) postponed_bug_sql = "select count(*) from zt_bug where product = '%d' and project='%d' and deleted = '0' and `status` <> 'closed' and resolution = 'postponed' " % ( productid, projectid) closed_bug_sql = "select count(*) from zt_bug where product='%d'and project='%d' and deleted = '0' and `status` = 'closed' " % ( productid, projectid) return bug_sql,resolved_bug_sql,not_resolved_bug_sql,postponed_bug_sql,closed_bug_sql #總的項目BUG情況統計 def test_project_bug(productid,projectid): #總bug數 all_bug=connect_db(sql_pakeage(productid,projectid)[0]) #已解決bug數 resolved_bug = connect_db(sql_pakeage(productid,projectid)[1]) # 未解決BUG數(當前顯示BUG狀態為未解決的。包含當前還沒被解決的、之前遺留的未解決、以及reopen的BUG(累計數據)) not_resolved_bug = connect_db(sql_pakeage(productid,projectid)[2]) # 延期BUG數 postponed_bug= connect_db( sql_pakeage(productid,projectid)[3]) # 已關閉BUG數 closed_bug = connect_db(sql_pakeage(productid,projectid)[4]) statistics_bug = { "總BUG數":all_bug[0],"已解決BUG": resolved_bug[0], "未解決BUG": not_resolved_bug[0], "已關閉BUG": closed_bug[0], "延期解決BUG": postponed_bug[0]} return statistics_bug #未解決及待驗證BUG人均分布 def test_pepole_bug(productid,projectid): #未解決BUG分布sql not_resolved_sql="select assignedTo,count(*) from zt_bug where product = '%d' and project='%d' and deleted = '0' and `status` = 'active' and assignedTo <> 'closed' group by assignedTo"%(productid,projectid) # 未解決BUG分布 not_resolved_bug=connect_db(not_resolved_sql) return list_dic(not_resolved_bug) #未解決BUG嚴重程度統計 def test_level_bug(productid,projectid): level_bug_sql="select severity,count(*) from zt_bug where product ='%d' and project='%d' and deleted = '0' and `status` = 'active' and assignedTo <> 'closed' group by severity"%(productid,projectid) level_bug=connect_db(level_bug_sql) return list_dic(level_bug) #已解決待驗證BUG分布 def test_verify_bug(productid,projectid): #已解決待驗證BUG分布sql not_verify_sql="select assignedTo,count(*) from zt_bug where product = '%d' and project='%d' and deleted = '0' and `status` ='resolved' and resolution='fixed' group by assignedTo"%(productid,projectid) # 已解決待驗證BUG分布 not_verify_bug = connect_db(not_verify_sql) return list_dic(not_verify_bug) #獲取項目名稱 def test_projectname(projectid): projectname="select `name` from zt_project where id='%d'"%(projectid) return connect_db(projectname)[0] #驗證項目名稱及產品名稱是否存在及是對應關系 def test_product_verify(productid,projectid): if productid: p_sql = "select project from zt_projectproduct where product=%d" % productid projectlist=connect_db(p_sql) if projectid & projectid in projectlist: return True else: return False else: return False
2、生成報表,報表基類較簡單就不貼碼了
from auto_report.setting import html_path,ip,report_path import os from auto_report.o_table import charts from auto_report.o_data import test_level_bug,test_project_bug,test_pepole_bug,test_verify_bug b_img=charts() #聲明圖表類 class create_report: #調取圖表方法,生成項目BUG狀態統計表生成 def test_project_bug_html(self,productid,projectid,t_time): if test_project_bug(productid,projectid): b_img.p_render("項目BUG狀態統計情況表", test_project_bug,'test_project_bug',productid,projectid,t_time) else: return False # 調取圖表方法,生成開發人員待解決BUG統計情況表生成 def test_pepole_bug_html(self,productid,projectid,t_time): if test_pepole_bug(productid,projectid): b_img.p_render("項目開發人員待解決BUG統計情況表", test_pepole_bug,'test_pepole_bug',productid,projectid,t_time) else: return False # 調取圖表方法,生成測試人員待驗證BUG統計情況表生成 def test_verify_bug_html(self,productid,projectid,t_time): if test_verify_bug(productid,projectid): b_img.line_render("項目測試人員待驗證BUG統計情況表", test_verify_bug,'test_verify_bug',productid,projectid,t_time) else: return False # 調取圖表方法,生成未解決BUG嚴重程度統計情況表生成 def test_level_bug_html(self,productid,projectid,t_time): if test_level_bug(productid,projectid): b_img.pie_render("項目未解決BUG嚴重程度統計情況表", test_level_bug,'test_level_bug',productid,projectid,t_time) else: return False #獲取HTML文件中文件,且生成圖片 def html_image(self,html_file_list): if html_file_list: for filename in html_file_list: self.new_filename=filename.replace('.html','') b_img.p_image(os.path.join(html_path,filename),self.new_filename) else: return False #獲取圖片文件中的圖片,且生成report文件 def img_report(self,img_file_list): if img_file_list: for img in img_file_list: self.f=open(report_path,"a+",encoding='utf-8') html='''<div><img src="%s/static/%s"></div>'''%(ip,img) self.f.write(html) self.f.close() else: return False
3、郵件發送
import yagmail import traceback from auto_report.setting import mail_info,to,cc,log from auto_report.o_data import sql_pakeage,test_projectname,connect_db from auto_report.o_util import read_file #發送郵件 def send_mail(productid,projectid): bug_sql=sql_pakeage(productid,projectid) bug_num=[] for sql in bug_sql: bug_num.append(int(connect_db(sql)[0])) project_name=test_projectname(projectid) subject="%s項目測試報告"%project_name str='''<div style="color:#000; font-size: 14px;font-family: arial;"> <span style="font-family: 微軟雅黑, Microsoft YaHei; font-size: 16px;">大家好:</span></div><div style="color:#000; font-size: 14px;font-family: arial;"> <span style="font-family: 微軟雅黑, Microsoft YaHei; font-size: 16px;"> %s項目,目前存在%s個BUG,已解決狀態%s個BUG,未解決狀態%s個BUG,延期處理狀態%s個BUG,已關閉狀態%s個BUG;請對應開發注意查收及修改自己名下的BUG。</span></div><div style="color:#000; font-size: 14px;font-family: arial;"><br></div><div style="color:#000; font-size: 14px;font-family: arial;"> <span style="font-family: 微軟雅黑, Microsoft YaHei; font-size: 16px;">各維度測試情況統計如下圖:</span><div><br></div></div>'''%(project_name,bug_num[0],bug_num[1],bug_num[2],bug_num[3],bug_num[4]) file_content=read_file("./report.html") content=str+file_content try: mail = yagmail.SMTP(**mail_info) # 解包方式傳入參數 mail.send(to=to, cc=cc, subject=subject, contents=content) # 發送郵件 except Exception as e: log.error("發送郵件出錯了,錯誤信息是:\n%s" % traceback.format_exc()) # 捕獲錯誤信息 else: log.info("發送郵件成功") # 發送成功日志
4、接口服務文件
from auto_report.o_mail import send_mail from auto_report.o_report import create_report from auto_report.setting import html_path,image_path,report_path import os,time from auto_report.o_data import test_product_verify from auto_report.o_util import clear,file_list import flask import json report=create_report() server=flask.Flask(__name__) #當前Python為一個服務 @server.route("/report") #get請求,且連接帶參數 def table_data(): productid=int(flask.request.args.get("productid")) #獲取參數產品ID projectid = int(flask.request.args.get("projectid")) #獲取參數項目ID t_time = str(int(time.time())) #獲取當前時間戳,作為本次文件的唯一標識 #判斷產品及項目輸入是否正確 if test_product_verify(productid, projectid): report.test_project_bug_html(productid, projectid, t_time) #項目BUG狀態統計表生成 report.test_level_bug_html(productid, projectid,t_time) #項目BUG待解決BUG嚴重程度統計表生成 report.test_pepole_bug_html(productid, projectid, t_time) #項目待解決BUG人員分布統計表生成 report.test_verify_bug_html(productid, projectid, t_time) #項目已解決待驗證BUG人員分布統計表成 #生成的圖表HTML轉圖片 html_file_list = file_list(html_path,t_time) report.html_image(html_file_list) #圖片組成報告 img_file_list = file_list(image_path,t_time) report.img_report(img_file_list) #發送報告 send_mail(productid,projectid) data = {"code": 200, "msg": "發送成功"} #清除本次報告report.html頁面產生的數據 clear(report_path) else: data={"code":-2,"msg":"參數錯誤"} #接口傳參錯誤 return json.dumps(data,ensure_ascii=False) #返回JSON格式 server.run(host="0.0.0.0",port=5000,debug=True) #啟動服務命令
運行效果:
備注:忽略內容啊,測試隨意寫的文字,文字可自行修改,哈哈哈哈