# Klark **Repository Path**: iojo/klark ## Basic Information - **Project Name**: Klark - **Description**: 测试工具项目,生成测试报告,生成测试数据 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-12-31 - **Last Updated**: 2021-04-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 项目初始化 1. 克隆项目后,找相关人员要到props.py文件放入conf路径。 2. 运行入口文件 python3 test_api_main.py 3. 调用接口/user/init初始化数据库和人员 ## 通过钉钉创建jira ### 使用方法: 1. 在群里引入机器人 在'群设置->智能群助手'中,引入钉钉企业机器人(注:钉钉企业机器人是普通机器人的升级版拥有一些额外能力) 2. 在群聊天中输入 > @JIRA 【A】这是一个问题 @不交房租白居易 JIRA机器人会在jira创建问题,并回复jira的链接 ### 格式 消息分3部分 ##### 1. @jira 只有@jira之后才会激活机器人的功能 ##### 2. 项目 - 【a】方舟 Ark - 【i】爱启航迭代优化 AQH2020 - 【不加任何内容】问题反馈 FB ##### 3. 标题 简要描述遇到的问题,会显示在jira的标题部分 ##### 4. 经办人 jira会将经办人,设置成被at到的人 ##### 5. 其他 jira会将发送消息的人,填入"报告人Dingtalk" jira会将群名,填入来源 由于条件限制,报告人会被设置成机器人 ### 原理 钉钉机器人会把聊天发给服务端,服务端把数据拆解包装好后,调用Jira的restful api创建问题 ### todos - todo:根据关键字,搜索jira并返回类似问题,类似智能客服机器人 - todo:更智能的防止重复提交,例如搜索关键字,提示用户有类似问题 - todo:根据关键字,问题自动归类 ## 创建jira,发送钉钉消息 ### 配置方法: 1. 在群里引入钉钉机器人:在'群设置->智能群助手'中,引入自定义机器人(自定义机器人功能,是企业机器人的子集) 2. 设置关键词验证 "jira通知",记录下access_token 3. 在jira后台 - 系统 - 网络钩子中,添加新的网络钩子{your_host}/dingmsg/send?access_token={my_access_token} ### 使用方法 正常在jira创建问题即可 ### 原理 jira创建问题后将问题信息发给服务端,服务端包装之后发给钉钉。 ### troubleshooting ##### 图片不显示 图床借用公司oss,直接传jira的图片会显示不出来 ##### @的人显示{code:0,msg:No result} - 新员工需要调用接口/user/add/?username={}&phone={}&realname={}添加 - 手机号或用户信息变更需要调用/user/add/?username={}&phone={}&realname={} - 显示全部用户信息/user/info/all - 删除重复用户需要调用/user/add/?username={}&id={} (为防止误删需要加用户id,id在all的接口里找) 因为@人需要手机号,但jira无法保存手机号,dingding调用用户信息需要管理员授权有点麻烦,所以用sqlite在服务端保存用户名和手机号的对应关系 ## 生成测试报告 测试报告氛围2部分:当日的缺陷状态情况,当日的测试用例执行情况 #### 怎样查询数据? 通过修改url的参数选择要查看某天的报告,如果没显示可能是格式不对,或没数据 例:/test/report?epic=ark-1093&date=2021-01-22&pageid=7964874 --> 搜索1月22日的ark-1093的epic,测试用例的pageid是7964874 #### 如何更新数据? 输入要统计的epic的id,点击更新,会重新从jira拉取数据,生成今天的数据 测试用例上传到confluence某个页面上,输入confluence页面的id并点击更新,生成今天的数据 #### 这个页面是如何工作的? 程序会根据epic,查询epic下的需求,然后查询需求下关联的bug,因此未关联的不会统计,关联后需要更新数据 程序会根据提供的pageid,去confluence搜索里面的xmind格式的附件,然后展开成json格式做统计 xmind的第5级被视为一条测试用例,请标注结果,每日上传 ### 测试工具 #### 复制产品(测试环境) #### 验证码(正式环境) ### 钉钉信息格式示例(markdown) ``` { "msgtype": "markdown", "markdown": { "title":"jira通知", "text": "#### 问题描述这里是 @150XXXXXXXX \n> 优先级:\n> ![screenshot](https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png)\n> ###### 10点20分发布 [天气](https://www.dingtalk.com) \n" }, "at": { "atMobiles": [ "150XXXXXXXX" ], "isAtAll": false } } ``` ### jira webhook 创建问题回调格式示例 ``` { "timestamp": 1610442819623, "webhookEvent": "jira:issue_created", "issue_event_type_name": "issue_created", "user": { "self": "http://jira.iqihang.com/rest/api/2/user?username=zhangyao", "name": "zhangyao", "key": "JIRAUSER10501", "emailAddress": "zhangyao@iqihang.com", "avatarUrls": { "48x48": "http://jira.iqihang.com/secure/useravatar?ownerId=JIRAUSER10501&avatarId=11100", "24x24": "http://jira.iqihang.com/secure/useravatar?size=small&ownerId=JIRAUSER10501&avatarId=11100", "16x16": "http://jira.iqihang.com/secure/useravatar?size=xsmall&ownerId=JIRAUSER10501&avatarId=11100", "32x32": "http://jira.iqihang.com/secure/useravatar?size=medium&ownerId=JIRAUSER10501&avatarId=11100" }, "displayName": "\xe5\xbc\xa0\xe5\x9e\x9a", "active": true, "timeZone": "Asia/Shanghai" }, "issue": { "id": "15247", "self": "http://jira.iqihang.com/rest/api/2/issue/15247", "key": "FB-71", "fields": { "issuetype": { "self": "http://jira.iqihang.com/rest/api/2/issuetype/10317", "id": "10317", "description": "\xe9\x97\xae\xe9\xa2\x98\xe5\x8f\x8d\xe9\xa6\x88", "iconUrl": "http://jira.iqihang.com/secure/viewavatar?size=xsmall&avatarId=10300&avatarType=issuetype", "name": "\xe5\x8f\x8d\xe9\xa6\x88", "subtask": false, "avatarId": 10300 }, "timespent": null, "project": { "self": "http://jira.iqihang.com/rest/api/2/project/10606", "id": "10606", "key": "FB", "name": "\xe9\x97\xae\xe9\xa2\x98\xe5\x8f\x8d\xe9\xa6\x88", "projectTypeKey": "software", "avatarUrls": { "48x48": "http://jira.iqihang.com/secure/projectavatar?avatarId=10324", "24x24": "http://jira.iqihang.com/secure/projectavatar?size=small&avatarId=10324", "16x16": "http://jira.iqihang.com/secure/projectavatar?size=xsmall&avatarId=10324", "32x32": "http://jira.iqihang.com/secure/projectavatar?size=medium&avatarId=10324" } }, "customfield_11000": null, "fixVersions": [], "aggregatetimespent": null, "resolution": null, "customfield_10500": null, "customfield_10105": null, "customfield_10501": null, "customfield_10502": null, "customfield_10503": null, "customfield_10504": null, "customfield_10900": null, "customfield_10505": null, "customfield_10901": null, "customfield_10506": null, "customfield_10902": null, "resolutiondate": null, "workratio": -1, "lastViewed": null, "watches": { "self": "http://jira.iqihang.com/rest/api/2/issue/FB-71/watchers", "watchCount": 0, "isWatching": false }, "created": "2021-01-12T09:13:38.867+0000", "priority": { "self": "http://jira.iqihang.com/rest/api/2/priority/3", "iconUrl": "http://jira.iqihang.com/images/icons/priorities/medium.svg", "name": "\xe4\xb8\xad", "id": "3" }, "customfield_10100": "0|i00q3z:", "customfield_10101": null, "labels": [], "customfield_10412": 100.0, "customfield_10413": { "self": "http://jira.iqihang.com/rest/api/2/customFieldOption/10107", "value": "No", "id": "10107" }, "timeestimate": null, "aggregatetimeoriginalestimate": null, "versions": [], "issuelinks": [], "assignee": { "self": "http://jira.iqihang.com/rest/api/2/user?username=zhangyao", "name": "zhangyao", "key": "JIRAUSER10501", "emailAddress": "zhangyao@iqihang.com", "avatarUrls": { "48x48": "http://jira.iqihang.com/secure/useravatar?ownerId=JIRAUSER10501&avatarId=11100", "24x24": "http://jira.iqihang.com/secure/useravatar?size=small&ownerId=JIRAUSER10501&avatarId=11100", "16x16": "http://jira.iqihang.com/secure/useravatar?size=xsmall&ownerId=JIRAUSER10501&avatarId=11100", "32x32": "http://jira.iqihang.com/secure/useravatar?size=medium&ownerId=JIRAUSER10501&avatarId=11100" }, "displayName": "\xe5\xbc\xa0\xe5\x9e\x9a", "active": true, "timeZone": "Asia/Shanghai" }, "updated": "2021-01-12T09:13:38.867+0000", "status": { "self": "http://jira.iqihang.com/rest/api/2/status/10210", "description": "\xe5\xbd\x93\xe5\x89\x8d\xe7\xbb\x8f\xe5\x8a\x9e\xe4\xba\xba\xe5\xba\x94\xe8\xb4\x9f\xe8\xb4\xa3\xe6\x8e\xa8\xe8\xbf\x9b\xe6\xad\xa4\xe9\x97\xae\xe9\xa2\x98\xe5\x88\xb0\xe8\xbf\x9b\xe8\xa1\x8c\xe4\xb8\xad\xe7\x9a\x84\xe7\x8a\xb6\xe6\x80\x81", "iconUrl": "http://jira.iqihang.com/", "name": "backlog", "id": "10210", "statusCategory": { "self": "http://jira.iqihang.com/rest/api/2/statuscategory/2", "id": 2, "key": "new", "colorName": "blue-gray", "name": "\xe5\xbe\x85\xe5\x8a\x9e" } }, "components": [], "timeoriginalestimate": null, "description": null, "customfield_10410": null, "timetracking": {}, "archiveddate": null, "customfield_10411": { "self": "http://jira.iqihang.com/rest/api/2/customFieldOption/10105", "value": "No", "id": "10105" }, "customfield_10401": null, "customfield_10402": null, "customfield_10403": null, "customfield_10404": null, "customfield_10602": null, "customfield_10800": null, "attachment": [{ "self": "http://jira.iqihang.com/rest/api/2/attachment/13907", "id": "13907", "filename": "jojo0007.jpg", "author": { "self": "http://jira.iqihang.com/rest/api/2/user?username=zhangyao", "name": "zhangyao", "key": "JIRAUSER10501", "emailAddress": "zhangyao@iqihang.com", "avatarUrls": { "48x48": "http://jira.iqihang.com/secure/useravatar?ownerId=JIRAUSER10501&avatarId=11100", "24x24": "http://jira.iqihang.com/secure/useravatar?size=small&ownerId=JIRAUSER10501&avatarId=11100", "16x16": "http://jira.iqihang.com/secure/useravatar?size=xsmall&ownerId=JIRAUSER10501&avatarId=11100", "32x32": "http://jira.iqihang.com/secure/useravatar?size=medium&ownerId=JIRAUSER10501&avatarId=11100" }, "displayName": "\xe5\xbc\xa0\xe5\x9e\x9a", "active": true, "timeZone": "Asia/Shanghai" }, "created": "2021-01-12T09:13:37.000+0000", "size": 11951, "mimeType": "image/jpeg", "content": "http://jira.iqihang.com/secure/attachment/13907/jojo0007.jpg", "thumbnail": "http://jira.iqihang.com/secure/thumbnail/13907/_thumb_13907.png" }], "customfield_10405": null, "customfield_10801": null, "customfield_10603": null, "aggregatetimeestimate": null, "customfield_10406": null, "customfield_10802": null, "customfield_10604": null, "customfield_10605": null, "customfield_10407": null, "customfield_10803": null, "customfield_10606": null, "customfield_10804": null, "customfield_10408": null, "customfield_10805": null, "customfield_10409": null, "customfield_10806": null, "customfield_10807": null, "customfield_10808": null, "customfield_10809": { "self": "http://jira.iqihang.com/rest/api/2/customFieldOption/10318", "value": "\xe6\xb5\x8b\xe8\xaf\x95", "id": "10318" }, "summary": "\xe6\xb5\x8b\xe8\xaf\x950004", "creator": { "self": "http://jira.iqihang.com/rest/api/2/user?username=zhangyao", "name": "zhangyao", "key": "JIRAUSER10501", "emailAddress": "zhangyao@iqihang.com", "avatarUrls": { "48x48": "http://jira.iqihang.com/secure/useravatar?ownerId=JIRAUSER10501&avatarId=11100", "24x24": "http://jira.iqihang.com/secure/useravatar?size=small&ownerId=JIRAUSER10501&avatarId=11100", "16x16": "http://jira.iqihang.com/secure/useravatar?size=xsmall&ownerId=JIRAUSER10501&avatarId=11100", "32x32": "http://jira.iqihang.com/secure/useravatar?size=medium&ownerId=JIRAUSER10501&avatarId=11100" }, "displayName": "\xe5\xbc\xa0\xe5\x9e\x9a", "active": true, "timeZone": "Asia/Shanghai" }, "subtasks": [], "reporter": { "self": "http://jira.iqihang.com/rest/api/2/user?username=zhangyao", "name": "zhangyao", "key": "JIRAUSER10501", "emailAddress": "zhangyao@iqihang.com", "avatarUrls": { "48x48": "http://jira.iqihang.com/secure/useravatar?ownerId=JIRAUSER10501&avatarId=11100", "24x24": "http://jira.iqihang.com/secure/useravatar?size=small&ownerId=JIRAUSER10501&avatarId=11100", "16x16": "http://jira.iqihang.com/secure/useravatar?size=xsmall&ownerId=JIRAUSER10501&avatarId=11100", "32x32": "http://jira.iqihang.com/secure/useravatar?size=medium&ownerId=JIRAUSER10501&avatarId=11100" }, "displayName": "\xe5\xbc\xa0\xe5\x9e\x9a", "active": true, "timeZone": "Asia/Shanghai" }, "customfield_10000": "{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@158f2af8[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6697e0b[overall=PullRequestOverallBean{stateCount=0, state=\'OPEN\', details=PullRequestOverallDetails{openCount=0, mergedCount=0, declinedCount=0}},byInstanceType={}], build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@29056968[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@64d1d365[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@400d6fe6[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@f6dfb98[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@d218d34[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@67812d0e[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@4c580c47[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@2c099f6f[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@2dc0fff7[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@43475e1c[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], devSummaryJson={\\" cachedValue\\ ":{\\" errors\\ ":[],\\" configErrors\\ ":[],\\" summary\\ ":{\\" pullrequest\\ ":{\\" overall\\ ":{\\" count\\ ":0,\\" lastUpdated\\ ":null,\\" stateCount\\ ":0,\\" state\\ ":\\" OPEN\\ ",\\" details\\ ":{\\" openCount\\ ":0,\\" mergedCount\\ ":0,\\" declinedCount\\ ":0,\\" total\\ ":0},\\" open\\ ":true},\\" byInstanceType\\ ":{}},\\" build\\ ":{\\" overall\\ ":{\\" count\\ ":0,\\" lastUpdated\\ ":null,\\" failedBuildCount\\ ":0,\\" successfulBuildCount\\ ":0,\\" unknownBuildCount\\ ":0},\\" byInstanceType\\ ":{}},\\" review\\ ":{\\" overall\\ ":{\\" count\\ ":0,\\" lastUpdated\\ ":null,\\" stateCount\\ ":0,\\" state\\ ":null,\\" dueDate\\ ":null,\\" overDue\\ ":false,\\" completed\\ ":false},\\" byInstanceType\\ ":{}},\\" deployment - environment\\ ":{\\" overall\\ ":{\\" count\\ ":0,\\" lastUpdated\\ ":null,\\" topEnvironments\\ ":[],\\" showProjects\\ ":false,\\" successfulCount\\ ":0},\\" byInstanceType\\ ":{}},\\" repository\\ ":{\\" overall\\ ":{\\" count\\ ":0,\\" lastUpdated\\ ":null},\\" byInstanceType\\ ":{}},\\" branch\\ ":{\\" overall\\ ":{\\" count\\ ":0,\\" lastUpdated\\ ":null},\\" byInstanceType\\ ":{}}}},\\" isStale\\ ":true}}", "aggregateprogress": { "progress": 0, "total": 0 }, "customfield_10200": null, "customfield_10201": null, "customfield_10400": null, "environment": null, "duedate": null, "progress": { "progress": 0, "total": 0 }, "comment": { "comments": [], "maxResults": 0, "total": 0, "startAt": 0 }, "votes": { "self": "http://jira.iqihang.com/rest/api/2/issue/FB-71/votes", "votes": 0, "hasVoted": false }, "worklog": { "startAt": 0, "maxResults": 20, "total": 0, "worklogs": [] }, "archivedby": null } } } ``` ### confluence附件格式 ``` {"results": [{"id": "15040886", "type": "attachment", "status": "current", "title": "购课短信.xmind", "metadata": {"mediaType": "application/vnd.xmind.workbook", "labels": {"results": [], "start": 0, "limit": 200, "size": 0, "_links": { "self": "http://confluence.iqihang.com/rest/api/content/15040886/label"}}, "_expandable": {"currentuser": "", "properties": "", "frontend": "", "editorHtml": ""}}, "extensions": {"mediaType": "application/vnd.xmind.workbook", "fileSize": 193972, "comment": ""}, "_links": { "webui": "/pages/viewpage.action?pageId=11865375&preview=%2F11865375%2F15040886%2F%E8%B4%AD%E8%AF%BE%E7%9F%AD%E4%BF%A1.xmind", "download": "/download/attachments/11865375/%E8%B4%AD%E8%AF%BE%E7%9F%AD%E4%BF%A1.xmind?version=2&modificationDate=1609904128000&api=v2", "self": "http://confluence.iqihang.com/rest/api/content/15040886"}, "_expandable": {"container": "/rest/api/content/11865375", "operations": "", "children": "/rest/api/content/15040886/child", "restrictions": "/rest/api/content/15040886/restriction/byOperation", "history": "/rest/api/content/15040886/history", "ancestors": "", "body": "", "version": "", "descendants": "/rest/api/content/15040886/descendant", "space": "/rest/api/space/TestSpace"}}], "start": 0, "limit": 10, "size": 1, "_links": {"self": "http://confluence.iqihang.com/rest/api/content/11865375/child/attachment", "base": "http://confluence.iqihang.com", "context": "" } } ```