<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
大家好,我是安果!
目前公司使用 Jira 作為專案管理工具,在每一次迭代完成後的覆盤會上,我們都需要針對本次迭代的 Bug 進行資料統計,以幫助管理層能更直觀的瞭解研發的程式碼質量
本篇文章將介紹如何利用統計 Jira 資料,並進行視覺化
首先,安裝 Python 依賴庫
# 安裝依賴庫 pip3 install jira pip3 install html-table pip3 install pyecharts pip3 install snapshot_selenium
其中
下面我們通過 7 個步驟來實現上面的功能
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狀態 """ # Jira首頁地址 self.server = 'https://jira.**.team' # Jira登入賬號資訊 self.basic_auth = ('使用者名稱', '密碼') # 建立一個使用者端連線資訊 self.jiraClinet = JIRA(server=self.server, basic_auth=self.basic_auth)
2-2 根據專案型別獲取看板 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 根據看板 id 獲取迭代 id 及迭代名稱
... # 獲取專案Sprint,讓使用者進行選擇 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 根據專案名、Bug 型別、迭代 id 組成 jsql 語句,並查詢資料
... def get_bug_status_jsql(self, bug_status: BUG_STATUS): """ 通過bug狀態,獲取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: # 關閉 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 統計資料
需要注意的是,使用 a 標籤組裝的連結不能直接跳轉,需要針對資料進行二次替換才能正常進行連結跳轉
from HTMLTable import ( HTMLTable ) ... def gen_html_table(self, datas): """ 初始化表單樣式 :return: """ table = HTMLTable(caption=f'實時BUG統計【{self.project_name}】,一共{len(datas)}個') # 表頭行 table.append_header_rows((('ID', '狀態', '優先順序', '責任人', '終端', 'URL'),)) # 新增資料 table.append_data_rows(datas) # 設定樣式 table.caption.set_style({'font-size': '15px'}) # 其他樣式設定 ... # 替換資料,便於展示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) ... # 生成本地檔案的資料 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 資料統計
首先,這裡按 Bug 責任人進行分組,然後按數目進行降序排列
然後,按 Bug 優先等級進行降序排列
最後,獲取每一個端的 Bug 總數
... # 2、統計每個人(按數目) 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總數排序:", datas_by_count) # 3、統計每個人(按優先順序) datas_by_priority = {} for item in datas_by_count: # 責任人 name = item[0] # 5個優先順序對應的數目 counts = self.get_assignee_count(lists, name) datas_by_priority[name] = counts # 排序(按優先順序多條件降序排列) 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優先順序排序:", datas_by_priority) # 4、根據終端進行統計分類 keys, values = self.get_end_type_count(lists) ...
2-7 視覺化
針對上面的 3 組資料,使用 pyecharts 繪製成柱狀圖和餅狀圖
... def draw_image(self, datas_by_count, datas_by_priority, keys, values): """ 繪製圖片 :param values: :param keys: :param datas_by_count: 按bug總數排序結果 :param datas_by_priority: 按bug優先順序排序結果 :return: """ # 1、按BUG總數排序繪製 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總數", [item[1] for item in datas_by_count]) # render 會生成本地 HTML 檔案,預設會在當前目錄生成 render.html 檔案 # 也可以傳入路徑引數,如 bar.render("mycharts.html") # bar.render(path=f'{sprint_name}-BUG總數.html') make_snapshot(snapshot, bar.render(), "./output/1.png") # 2、按優先順序排序繪製 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優先順序.html') make_snapshot(snapshot, bar2.render(), "./output/2.png") # 3、根據終端來繪製餅圖 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="{b}: {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) ...
通過上面的操作,每次只需要輸入專案型別、迭代版本號、要統計的 Bug 型別,就能統計出所需要的資料並繪製成圖表
到此這篇關於利用Python統計Jira資料並視覺化的文章就介紹到這了,更多相關Python統計Jira資料內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45