通用技术 【Chrome 插件】TAPD 创建 bug、状态变更发送钉钉通知

中建电商-质量部 · April 02, 2021 · Last by okk replied at December 10, 2022 · 5568 hits

背景:

公司使用 TAPD 作为项目、测试流程、测试用例、缺陷管理平台,而日常公司内部的交流工具为钉钉;TAPD 与钉钉无法在系统上进行很好的交互,在提交 bug 或者其他任务状态发生变化时,需要及时通知到相关的同事进行及时处理。

解决方案:

编写 Chrome 插件,对需要关注的任务、bug 进行状态监听;当状态发生流转时,能够通过插件调用钉钉机器人,及时的在工作群中通知到相关同事。

目前效果:


严重级别及以上、优先级为高及以上的 bug,状态流转至已解决的耗时由平均 4.8个小时提升至平均 2.9个小时。极大程度上提高了 bug 的解决效率和测试效率。

原理:

Chrome 插件编写 Java Script 对按钮进行监听,判断字段发生变化并且满足条件时,调用 XMLHttpRequest 对已设置好的钉钉群机器人发送消息,即可实现像上图一样的效果。是不是很 easy!

代码:

// var dingdingUrl = "https://oapi.dingtalk.com/robot/send?access_token=842de0b90ff76bfce0830ab71097dee74fad0a17ba0963a56a3fffa7a940449b";

$(function () {
    isSend();

    //提交缺陷
    $('#_view').click(function () {
        localStorage.setItem('preUrl', window.location.href);
    });

    //bug状态流转
    $('#update_status_btn').click(function (){
        localStorage.setItem('preUrl', window.location.href);
    });

    //从缓存拿上个页面地址进行对比,并进行发送
    async function isSend() { 
        var _preUrl = localStorage.getItem('preUrl');
        var _referrer = document.referrer;
        if (_preUrl == _referrer) {
            var _bugPriority = $('#ContentPriority').attr('data-editable-value');
            var _bugSeverity = $('#ContentSeverity').attr('data-editable-value');
            var _bugStatus = $('a[workflow-status-change=entityViewStatusChange]').attr('title');
            //根据bug等级、状态、优先级决定是否进行发送钉钉
            if(_bugSeverity == "致命" || _bugSeverity == "严重" || _bugPriority == "紧急" || _bugPriority == ""){
                if(_bugStatus != "已关闭" && _bugStatus != "接受/处理" ){
                    sendingMsg(await setBugParams())
                }
            }

            localStorage.removeItem('preUrl');
        }
    }

    async function setBugParams(){
        var _bugUrl = getBugUrl(location.href);
        var _bugTitle = $('#bug_title_view .editable-value').attr('title');
        var _bugPriority = $('#ContentPriority').attr('data-editable-value');
        var _bugSeverity = $('#ContentSeverity').attr('data-editable-value');
        var _bugModule = $('#Content所属模块').attr('data-editable-value');
        var _bugStatus = $('a[workflow-status-change=entityViewStatusChange]').attr('title');
        var _bugOwners = $('#ContentCurrentOwner').text();
        _bugOwners = _bugOwners.replace(/\(.*?\)/g,'');
        var _bugPriority = $('#ContentPriority').attr('data-editable-value');
        var _bugSeverity = $('#ContentSeverity').attr('data-editable-value');
        var _mobileList =await getMobiles(_bugOwners);

        var params = {
            "msgtype": "text",
            "text": {
            "content": "BUG:" + _bugTitle + 
            "\n状态:" + _bugStatus + 
            "\n优先级:" + _bugPriority + 
            "\n级别:" + _bugSeverity + 
            "\n所属模块:" + _bugModule + 
            "\n链接:" + _bugUrl
            },
            "at":{
                "atMobiles": _mobileList,
                "isAtAll": false
            }

        };
        return params;
    }

    //发送消息XMLHTTP
    function sendingMsg(params) {
        if (params == 0){
            return;
        }
        var xhr = new XMLHttpRequest();
        xhr.open("POST", dingdingUrl, true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (window.Notification) {
                    chrome.extension.sendRequest({ type: 1, name: "发送钉钉通知", msg: xhr.responseText }, function (response) {
                        console.log(response);
                    });
                } else { alert('消息已发送,当前浏览器不支持推送消息'); }
            }
        }
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.send(JSON.stringify(params));
    }
    //拼接bug URL
    function getBugUrl(url){
        var tmpList1 = splitStr(url,"?");
        var tmpList2 = splitStr(tmpList1[1],"&");
        var bugUrl = tmpList1[0] + "?";
        for(var i=0;i<tmpList2.length;i++){
            console.log(tmpList2[i]);
            if(tmpList2[i].match("bug_id=")){
                bugUrl = bugUrl + tmpList2[i];
                break;
            }
        }
        return bugUrl;
    }
    //获取处理人联系电话
    async function getMobiles(bugOwners){
        var mobileList = splitStr(bugOwners,";").filter((v) => v)
        for(let i=0;i<mobileList.length;i++){
            //后端封装了个简单的接口,用于获取通知人的电话
            url='http://easytest.yzw.cn/user/getPhone?tapdUserAccount='+mobileList[i];
            mobileList[i] = await getMobile(url);
        }
        return mobileList;
    }
    //单个获取电话号码
    async function getMobile(url){
        return await fetch(url).then(response=>response.text())
    }

    //字符串解析分割
    function splitStr(str,regx){
        var result = str.split(regx);
        return result;
    }

});

说明:本插件脚本中,封装了获取 TAPD 用户电话号码的接口,因为要实现在钉钉中 @ 到某一个人。TAPD 的用户名跟钉钉的电话号码是维护在一个表里头,用接口进行返回。如果不需要接口的方式,也可以简单的用 Map 的方式在脚本中维护即可;如果不需要实现 @ 到某个人,那么也可以不用获取电话号码。

脚本写好后,需要以插件的形式安装到 Chrome 中。以下介绍下整体插件文件目录以及安装过程:

插件文件目录:

写好之后压缩了发给同事们吧~

## 安装步骤:

  • 1. 解压插件压缩包
  • 2. 打开 Chrome 浏览器-->扩展程序
  • 3. 加载插件
  • 4. 确保插件是打开状态
  • 5. 在需要通知的钉钉群中,增加群助手 机器人 将上图中生成的 webhook url 复制到脚本中;后续就会在该群中同步消息 ### 全部设置完成后,即可实现上文效果展示中的样子;当然,除了 bug 还可以监听其他内容,根据自己的需要进行扩展吧~ Done!
共收到 22 条回复 时间 点赞

TAPD 的状态变化通知至钉钉 仅是应用的一种;chrome 插件可以实现多种多样的功能扩展:比如 web 测试的辅助 -- 表单自动填写;比如自动检查页面上的一些元素;比如...很多很多,希望能帮到大家

这个思路挺强的,没想到通过 chrome 插件来弄。
我的做法是通过 tapd 的 api 做定时任务来获取缺陷变更记录,根据状态的变化通知到相应的人,确实不如插件来的直接。

MarvinWu 回复

tapd 的 api 我们也在调用,但主要是用于数据统计。后续会介绍到我们怎么去基于 TAPD 去做各个维度的质量看板(项目维度、团队维度、个人维度),让数据为质量说话,让过程与结果透明化、公平化

涨知识了,期待后续介绍。

Author only

请问一下楼主,企业微信也可以吗

插件化是一种思路,但是建议是做内部服务,tapd 做一个 saas,包装 buginfo,关键场景等等定义一系列数据结构。钉钉 api 做一个 saas,中间层一个 pm 服务的 saas(包含多少时间未处理提醒和流转状态等等),这个 saas 去统一调用二边。企业微信等价 tapd,稍微麻烦点,需要拿组织架构权限和再申请一个应用。

桑七昂 回复

企业微信应该本身就能够很好的支持通知机制吧?毕竟都是腾讯的

18Floor has deleted
19Floor has deleted
12Floor has deleted
13Floor has deleted

发了啊

15Floor has deleted
Author only
Author only
陈子昂 回复

楼主公司的采购充分说明了采购负责人 “鸡蛋不要放在一个篮子里” 的理念,用两个不同生态圈的工具在一起协作😂
猫总 DOGE 买起来啊😎

Author only
刘建国 回复

因为这个脚本是直接 @ 到某一个人,所以需要维护电话号码,钉钉机器人需要通过电话号码 @ 到某一个人。我建议你可以先不要 @ 到人的功能,先把插件调通。
另外,我建议你先理解这个插件的原理和脚本的逻辑,才好灵活调整成你要的东西哈

23Floor has deleted
Author only
Author only

老哥求一份插件,自用,谢谢,343078946@qq.com

大佬能发一份插件不,自用,谢谢,528634141@qq.com

老哥求插件 10453164@qq.com

老哥求插件 2236603429@qq.com

大佬能发一份插件不,自用,谢谢,952628613@qq.com

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up