利用Python統(tǒng)計Jira數(shù)據(jù)并可視化
大家好,我是安果!
目前公司使用 Jira 作為項目管理工具,在每一次迭代完成后的復(fù)盤會上,我們都需要針對本次迭代的 Bug 進(jìn)行數(shù)據(jù)統(tǒng)計,以幫助管理層能更直觀的了解研發(fā)的代碼質(zhì)量
本篇文章將介紹如何利用統(tǒng)計 Jira 數(shù)據(jù),并進(jìn)行可視化
1. 準(zhǔn)備
首先,安裝 Python 依賴庫
#?安裝依賴庫 pip3?install?jira pip3?install?html-table pip3?install?pyecharts pip3?install?snapshot_selenium
其中
- jira 使用 jsql 語法從在項目中獲取需要的數(shù)據(jù)
- html-table 用于生成一個 HTML 格式的表格數(shù)據(jù)
- pyecharts 和 snapshot_selenium 用于數(shù)據(jù)可視化
2. 實戰(zhàn)一下
下面我們通過 7 個步驟來實現(xiàn)上面的功能
2-1 登錄獲取客戶端連接對象
from?jira?import?JIRA class?JiraObj(object): ????def?__init__(self,?bug_style,?project_type): ????????""" ????????:param?project_name ????????:param?sprint:?迭代號碼 ????????:param?bug_style:?BUG狀態(tài) ????????""" ????????#?Jira首頁地址 ????????self.server?=?'https://jira.**.team' ????????#?Jira登錄賬號信息 ????????self.basic_auth?=?('用戶名',?'密碼') ????????#?創(chuàng)建一個客戶端連接信息 ????????self.jiraClinet?=?JIRA(server=self.server,?basic_auth=self.basic_auth)
2-2 根據(jù)項目類型獲取看板 id
... ????????#?獲取boards看板 ????????#?所有看板信息 ????????boards?=?[(item.id,?item.name)?for?item?in?self.jiraClinet.boards()] ????????board_id?=?self.__get_board_id(boards,?project_type) ????????print("看板id:",?board_id) ... ????def?__get_board_id(self,?boards,?project_type): ????????""" ????????獲取看板id ????????:param?project_type: ????????:return: ????????""" ????????board_id?=?1 ????????for?item?in?boards: ????????????if?(project_type?==?PROJ_TYPE.Type1?and?item[1]?==?'t1')?or?( ????????????????????project_type?==?PROJ_TYPE.Type2?and?item[1]?==?'t2'): ????????????????board_id?=?item[0] ????????????????break ????????return?board_id ..
2-3 根據(jù)看板 id 獲取迭代 id 及迭代名稱
... ?#?獲取項目Sprint,讓用戶進(jìn)行選擇 ????????sprints?=?self.jiraClinet.sprints(board_id=board_id) ????????for?item?in?sprints: ????????????if?str(sprint_no)?in?item.name: ????????????????self.sprint_id?=?item.id ????????????????self.sprint_name?=?item.name ????????????????print(f"選擇Sprint,id:{self.sprint_id},name:{self.sprint_name}") ????????????????break ...
2-4 根據(jù)項目名、Bug 類型、迭代 id 組成 jsql 語句,并查詢數(shù)據(jù)
... ?def?get_bug_status_jsql(self,?bug_status:?BUG_STATUS): ????????""" ????????通過bug狀態(tài),獲取jsql ????????:param?bug_status: ????????:return: ????????""" ????????status_jsql?=?'' ????????if?bug_status?==?BUG_STATUS.ALL: ????????????status_jsql?=?'?' ????????elif?bug_status?==?BUG_STATUS.TO_VERIFY: ????????????#?待驗證(已解決) ????????????status_jsql?=?'?AND?status?=?已解決?' ????????elif?bug_status?==?BUG_STATUS.TO_FIXED: ????????????#?待解決(打開、重新打開、處理中) ????????????status_jsql?=?'?AND?status?in?(打開,?重新打開,?處理中)?' ????????elif?bug_status?==?BUG_STATUS.CLOSED: ????????????#?關(guān)閉 ????????????status_jsql?=?'?AND?status?=?Closed?' ????????elif?bug_status?==?BUG_STATUS.TO_FIXED_CONTAIN_DELAY: ????????????#?待解決(打開、重新打開、處理中、延期處理) ????????????status_jsql?=?'?AND?status?in?(打開,?延期處理,?重新打開,?處理中)?' ????????return?status_jsql ... jql?=?f'project?=?{project_name}?and?issuetype?=?故障??{self.get_bug_status_jsql(self.bug_style)}?AND?Sprint?=?{self.sprint_id}?ORDER?BY?priority?desc,?updated?DESC' ????????print(jql) ????????lists?=?self.get_issue_list(jql) ...
2-5 生成本地 HTML 統(tǒng)計數(shù)據(jù)
需要注意的是,使用 a 標(biāo)簽組裝的鏈接不能直接跳轉(zhuǎn),需要針對數(shù)據(jù)進(jìn)行二次替換才能正常進(jìn)行鏈接跳轉(zhuǎn)
from?HTMLTable?import?( ????HTMLTable ) ... ?def?gen_html_table(self,?datas): ????????""" ????????初始化表單樣式 ????????:return: ????????""" ????????table?=?HTMLTable(caption=f'實時BUG統(tǒng)計【{self.project_name}】,一共{len(datas)}個') ????????#?表頭行 ????????table.append_header_rows((('ID',?'狀態(tài)',?'優(yōu)先級',?'責(zé)任人',?'終端',?'URL'),)) ????????#?添加數(shù)據(jù) ????????table.append_data_rows(datas) ????????#?設(shè)置樣式 ????????table.caption.set_style({'font-size':?'15px'}) ????????#?其他樣式設(shè)置 ????????... ????????#?替換數(shù)據(jù),便于展示href地址 ????????html?=?table.to_html().replace("<",?"<").replace(">",?">").replace(""",?'"') ????????with?open(f"./output/{self.project_name}-bug_{current_time()}.html",?'w',?encoding='utf-8')?as?file: ????????????file.write(html) ... #?生成本地文件的數(shù)據(jù) output_tuples?=?tuple([ ????????????(item.get("key"),?item.get("status"),?item.get("priority"),?item.get('duty'),?item.get('end_type'), ?????????????f'<a?href="{item.get(" rel="external nofollow" url")}"?target="_blank">點我查看</a>')?for?item?in?lists]) #?生成本地HTML文件 self.gen_html_table(output_tuples) ..
2-6 數(shù)據(jù)統(tǒng)計
首先,這里按 Bug 責(zé)任人進(jìn)行分組,然后按數(shù)目進(jìn)行降序排列
然后,按 Bug 優(yōu)先等級進(jìn)行降序排列
最后,獲取每一個端的 Bug 總數(shù)
... ????????#?2、統(tǒng)計每個人(按數(shù)目) ????????datas_by_count?=?{} ????????for?item?in?lists: ????????????datas_by_count[item.get("duty")]?=?datas_by_count.get(item.get("duty"),?0)?+?1 ????????#?降序排序 ????????datas_by_count?=?sorted(datas_by_count.items(),?key=lambda?item:?item[1],?reverse=True) ????????#?print("按Bug總數(shù)排序:",?datas_by_count) ????????#?3、統(tǒng)計每個人(按優(yōu)先級) ????????datas_by_priority?=?{} ????????for?item?in?datas_by_count: ????????????#?責(zé)任人 ????????????name?=?item[0] ????????????#?5個優(yōu)先級對應(yīng)的數(shù)目 ????????????counts?=?self.get_assignee_count(lists,?name) ????????????datas_by_priority[name]?=?counts ????????#?排序(按優(yōu)先級多條件降序排列) ????????datas_by_priority?=?sorted(datas_by_priority.items(), ???????????????????????????????????key=lambda?item:?(item[1][0],?item[1][1],?item[1][2],?item[1][3]),?reverse=True) ????????#?print("按Bug優(yōu)先級排序:",?datas_by_priority) ????????#?4、根據(jù)終端進(jìn)行統(tǒng)計分類 ????????keys,?values?=?self.get_end_type_count(lists) ...
2-7 可視化
針對上面的 3 組數(shù)據(jù),使用 pyecharts 繪制成柱狀圖和餅狀圖
... ??????def?draw_image(self,?datas_by_count,?datas_by_priority,?keys,?values): ????????""" ????????繪制圖片 ????????:param?values: ????????:param?keys: ????????:param?datas_by_count:?按bug總數(shù)排序結(jié)果 ????????:param?datas_by_priority:?按bug優(yōu)先級排序結(jié)果 ????????:return: ????????""" ????????#?1、按BUG總數(shù)排序繪制 ????????bar?=?( ????????????Bar().set_global_opts( ????????????????title_opts=opts.TitleOpts(title=f"{self.project_name}",?subtitle=f"{self.sprint_name}"))) ????????bar.add_xaxis([item[0]?for?item?in?datas_by_count]) ????????bar.add_yaxis(f"BUG總數(shù)",?[item[1]?for?item?in?datas_by_count]) ????????#?render?會生成本地?HTML?文件,默認(rèn)會在當(dāng)前目錄生成?render.html?文件 ????????#?也可以傳入路徑參數(shù),如?bar.render("mycharts.html") ????????#?bar.render(path=f'{sprint_name}-BUG總數(shù).html') ????????make_snapshot(snapshot,?bar.render(),?"./output/1.png") ????????#?2、按優(yōu)先級排序繪制 ????????bar2?=?( ????????????#?Bar(init_opts=opts.InitOpts(theme=ThemeType.INFOGRAPHIC)) ????????????Bar() ????????????????.add_xaxis([item[0]?for?item?in?datas_by_priority]) ????????????????.add_yaxis(self.__get_priority(BUG_PRIORITY.Highest),?[item[1][0]?for?item?in?datas_by_priority], ???????????????????????????color='#6aa84f') ????????????????.add_yaxis(self.__get_priority(BUG_PRIORITY.High),?[item[1][1]?for?item?in?datas_by_priority], ???????????????????????????color='#a2c4c9') ????????????????.add_yaxis(self.__get_priority(BUG_PRIORITY.Medium),?[item[1][2]?for?item?in?datas_by_priority], ???????????????????????????color="#ff9900") ????????????????.add_yaxis(self.__get_priority(BUG_PRIORITY.Low),?[item[1][3]?for?item?in?datas_by_priority], ???????????????????????????color="#ea9999") ????????????????.add_yaxis(self.__get_priority(BUG_PRIORITY.Lowest),?[item[1][4]?for?item?in?datas_by_priority], ???????????????????????????color="#980000") ????????????????.set_global_opts( ????????????????title_opts=opts.TitleOpts(title=f"{self.project_name}",?subtitle=f"{self.sprint_name}")) ????????) ????????#?bar2.render(path=f'{sprint_name}-BUG優(yōu)先級.html') ????????make_snapshot(snapshot,?bar2.render(),?"./output/2.png") ????????#?3、根據(jù)終端來繪制餅圖 ????????if?len(keys)?>?0?and?len(values)?>?0: ????????????c?=?( ????????????????Pie() ????????????????????.add("",?[list(z)?for?z?in?zip(keys,?values)]) ????????????????????.set_global_opts(title_opts=opts.TitleOpts(title="各端BUG分布")) ????????????????????.set_series_opts(label_opts=opts.LabelOpts(formatter=":?{c}")) ????????????) ????????????make_snapshot(snapshot,?c.render(),?f"./output/{self.project_name}_end.png") ????????#?4、合并兩張圖片 ????????self.concatenate_img(['./output/1.png',?'./output/2.png'],?img_name=f'./output/{self.sprint_name}_bug.png', ?????????????????????????????axis=1) ...
3. 總結(jié)
通過上面的操作,每次只需要輸入項目類型、迭代版本號、要統(tǒng)計的 Bug 類型,就能統(tǒng)計出所需要的數(shù)據(jù)并繪制成圖表
到此這篇關(guān)于利用Python統(tǒng)計Jira數(shù)據(jù)并可視化的文章就介紹到這了,更多相關(guān)Python統(tǒng)計Jira數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python使用多進(jìn)程運行含有任意個參數(shù)的函數(shù)
這篇文章主要介紹了Python使用多進(jìn)程運行含有任意個參數(shù)的函數(shù),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05python面試題Python2.x和Python3.x的區(qū)別
這篇文章主要介紹了python面試題Python2.x和Python3.x的區(qū)別 ,在面試中也經(jīng)常會問到,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05Python操作excel的方法總結(jié)(xlrd、xlwt、openpyxl)
這篇文章主要給大家介紹了關(guān)于Python操作excel的一些方法,其中包括xlrd、xlwt、openpyxl的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09python實現(xiàn)逆波蘭計算表達(dá)式實例詳解
這篇文章主要介紹了python實現(xiàn)逆波蘭計算表達(dá)式的方法,較為詳細(xì)的分析了逆波蘭表達(dá)式的概念及實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-05-05Python讀取英文文件并記錄每個單詞出現(xiàn)次數(shù)后降序輸出示例
這篇文章主要介紹了Python讀取英文文件并記錄每個單詞出現(xiàn)次數(shù)后降序輸出,涉及Python文件讀取、字符串替換、分割以及字典遍歷、排序等相關(guān)操作技巧,需要的朋友可以參考下2018-06-06