前言
问题反馈是测试过程中一个非常重要的环节,不仅是测试人员工作成果的体现,也是项目质量跟踪的重要依据。提交一个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字段赋值。
- 常规字段的赋值
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系统进行项目管理,很多细节没有展开讲,读者有任何问题可以在下方留言。