基于Redmine的无线Bug反馈解决方案

前言

问题反馈是测试过程中一个非常重要的环节,不仅是测试人员工作成果的体现,也是项目质量跟踪的重要依据。提交一个Bug的时候,我们一般需要给出Bug描述,复现步骤,截图以及日志等,尽可能提供更多的信息方便开发定位问题。这个过程一般要消耗测试人员大量的时间,尤其是上传截图,抓取日志,获取设备信息等。作者所在的项目组内使用开源系统Redmine进行Bug的反馈及跟进。据统计,一个熟练的测试人员从发现问题到把完整Bug信息提交到Redmine系统,大概需要5分钟时间。大部分时候,我们执行一条测试用例的时间还不到5分钟。也就是说,有可能我们每天花在提bug上的时间比测试时间还长。因此,我们非常有必要对传统的提bug方式进行改进。于是我们对Redmine的API进行封装,通过无线方式快速提交Bug,将提Bug的时间减少到了1分钟以下。本文主要介绍Redmine Java API的应用以及无线Bug反馈工具的实现方案。

Redmin API及其应用

Redmine对外提供REST API,用户可以非常方便的调用API进行操作,在Redmine的官方文档中有详细的介绍,感兴趣的同学可以自行查看。这里主要介绍一个第三方团体taskadapter开发的redmine java api

redmine-java-api介绍

1.接入方式
你可以通过Gradle或者Maven的方式直接在项目中引用

dependencies {
    compile 'com.taskadapter:redmine-java-api:<current-version>'
}

2.示例用法

String uri = "https://www.hostedredmine.com";
String apiAccessKey = "a3221bfcef5750219bd0a2df69519416dba17fc9";
String projectKey = "taskconnector-test";
Integer queryId = null; // any

RedmineManager mgr = RedmineManagerFactory.createWithApiKey(uri, apiAccessKey);
IssueManager issueManager = mgr.getIssueManager();
List<Issue> issues = issueManager.getIssues(projectKey, queryId);
for (Issue issue : issues) {
        System.out.println(issue.toString());
}

// Create issue
Issue issueToCreate = IssueFactory.createWithSubject("some subject");
Issue createdIssue = issueManager.createIssue(projectKey , issueToCreate);

// Get issue by ID:
Issue issue = issueManager.getIssueById(123);

3.获取自定义字段

Issue issue = ...
List<CustomFieldDefinition> customFieldDefinitions = mgr.getCustomFieldManager().getCustomFieldDefinitions();
// sample implementation for getCustomFieldByName() is in CustomFieldResolver (test class).
// in prod code you would typically know the custom field name or id already 
CustomFieldDefinition customField1 = getCustomFieldByName(customFieldDefinitions, "my_custom_1");
String custom1Value = "some value 123";
issue.addCustomField(CustomFieldFactory.create(customField1.getId(), customField1.getName(), custom1Value));
issueManager.update(issue);

应用实践

为了符合项目需求,我们的redmine issue页面增加了很多自定义字段,如下图所示。图中带*的字段都是必填字段。而且跟踪方式,状态,优先级,项目,模块,Bug引入者这几个字段都是只能选择给定的取值。因此,我们第一步是要获取这些字段的取值。

我们这里通过两个示例来介绍一下Issue中列表取值的获取方式,其他字段都很类似。
1.获取自定义的项目信息

 public List<String> getFProjects(){
  List<CustomFieldDefinition> customfieldlist = null;
  List<String> projectlist = new ArrayList<String>();
  try {
   customfieldlist = mgr.getCustomFieldManager().getCustomFieldDefinitions();
   for(int i=0;i<customfieldlist.size();i++){
    if(customfieldlist.get(i).getName().equals("项目"))
     projectlist = customfieldlist.get(i).getPossibleValues();
   }
  } catch (RedmineException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return projectlist;
 }

2.获取某个项目下的关联用户

 public List<User> getFUsers(){
  List<User> userlist = null;
  try {
   Project project = mgr.getProjectManager().getProjectById(64);
   List<Tracker> trackers = (List<Tracker>) project.getTrackers();
   trackers.get(0).getName();
  } catch (RedmineException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return userlist;
 }

接下来,是最重要的步骤,即把各个Issue字段信息拼装起来提交到redmine。我们在第一节的示例代码中介绍了创建issue的用法,这里我们介绍下如何给各issue字段赋值。

  1. 常规字段的赋值
JSONObject assigner = JSONObject.parseObject(mybug.getAssign());
User user = userManager.getUserById(assigner.getInteger("id"));      
Issue issue = new Issue();
ProjectManager projectMgr = mgr.getProjectManager();
Project project = projectMgr.getProjectById(64);
issue.setProject(project);
issue.setAssignee(user);
issue.setSubject(mybug.getTitle());
issue.setDescription(mybug.getDescription());

2.自定义字段赋值

String modulename = mybug.getModels().equals("")?"前端-生活":mybug.getModels();
CustomField customField1 = CustomFieldFactory.create(19, "模块", modulename);
String userid = (assigner != null)?assigner.get("id").toString():"110";
CustomField customField2 = CustomFieldFactory.create(20, "Bug引入者", userid);
issue.addCustomField(customField1);
issue.addCustomField(customField2);

3.添加附件

String filename = attachments.getString(i);
String localPath = System.getProperty("catalina.home")+"/webapps/attachments/"+filename;
FileDownload.downloadFile("http://202.69.28.31/attachments/"+filename, localPath);
File attachmentFile = new File(localPath);
if(attachmentFile != null){
          AttachmentManager attachmentMgr = mgr.getAttachmentManager();
          attachmentMgr.addAttachmentToIssue(issue.getId(), attachmentFile, "application/octet-stream");
}

小结

通过前面的介绍,相信对redmine java api的使用已经有了初步的了解,对API的运用,主要是获取信息和提交信息两个方式。那么,我们如何将api应用到无线app中呢。下面我们将详细介绍我们的实现方案。

无线Bug反馈工具解决方案

其实无线Bug反馈工具最直接的方式就是开发一个App,集成上述Api的功能进去,然后收集用户填写的Bug信息,提交到redmine系统。我们的方案基本上也是按这个思路,只不过为了克服网络以及用户登录的问题,做了很多其他工作。下面是我们开发的界面截图。

界面截图

1.获取基本项目信息

为了提高效率,我们先把issue中需要预设的字段取值拉取下来,存放在app本地,只需要定时更新即可,这样加快了读取信息的速度。下面是获取信息的主要代码,最终会生成一个json文件,将放到程序目录下。如上图所示,每个字段的列表信息都是从redmine系统通过该方式获取的。

public String getFInfo(HttpServletRequest req,HttpServletResponse rep){
  List<String> projectlist = redmineService.getFProjects();
  List<String> modulelist = redmineService.getFModules();
  List<User> userlist = redmineService.getAllUsers();
  List<Version> versionlist = redmineService.getTargetVersion(64);
  JSONArray fusers = new JSONArray();
  for(User user : userlist){
   if(user.getFullName().contains("F") || user.getFullName().contains("交付")
     || user.getFullName().contains("生活") || user.getFullName().contains("理财")
     || user.getFullName().contains("运营") || user.getFullName().contains("基础服务")
     || user.getFullName().contains("应用架构") || user.getFullName().contains("f")){
    JSONObject json = new JSONObject();
    json.put("id", user.getId());
    json.put("name", user.getFullName());
    fusers.add(json);
   } 
  }
  JSONArray fversions = new JSONArray();
  for(Version version : versionlist){
   JSONObject json = new JSONObject();
   json.put("id", version.getId());
   json.put("name", version.getName());
   fversions.add(json);
  }
  JSONObject retJSON = new JSONObject();
  retJSON.put("project", projectlist);
  retJSON.put("module", modulelist);
  retJSON.put("user", fusers);
  retJSON.put("version", fversions);
  return buildResponse(ResponseEnum.SUCCESS,retJSON);
 }

2. 填写bug描述

我们获取到测试设备的基本信息,预设到描述中,并提供一个模板以供参考,如下图所示。


描述

3.获取截图

用户在测试过程中自由截图,然后通过app提交bug的时候,可以通过选择图片选项来选取截图用于提交。具体实现方式这里不做阐述。

4. 获取日志

我们提供了一个logcat和一个crash抓取工具,可以获取某个应用的日志信息以及crash log信息。后面我们将有专题文章对这两个工具的实现方式进行介绍,这里不做详细展开。我们在文件这个选项中,将抓取到的程序log或crash日志提交到redmine。

日志

5.登录并提交

为了方便跟踪,提交bug是需要登录的,我们将redmine跟公司的统一登录体系打通,登录成功后,就可以将bug信息提交到redmine系统。

6.小结

该工具只是我们开发的测试助手中的一个功能,我们还集成了crash监控,性能监控,构建包下载等功能。后续我们将会有更多专题介绍其他工具的实现方案。

测试助手

总结

本文通过对redmine api的应用,介绍了一个无线Bug反馈的解决方案。通过这种方式,我们在提交bug的时候,涉及到截图,日志,设备信息的部分几乎可以忽略不计,再加上选择和填写基本信息,整个过程不超过1分钟。对测试效率的提升带来了极大的帮助。本文只是介绍一种解决思路,毕竟不是所有团队都是用redmine系统进行项目管理,很多细节没有展开讲,读者有任何问题可以在下方留言。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容