luming 发表于 2011-10-29 16:56:59

Mantis解析

此系列文章,整理后,删改一些内容为《Mantis深入学习》,发表在了《51测试天地》第23期电子杂志上,在这里感谢51testing的编辑采用我的文章并且允许我发表《mantis解析》原文在blog上。

序章

文章的题目比较大,说mantis解析可能过了些,只是说些自己在使用mantis过程中,如何分析和处理mantis源码,以适合自己的需求。

我原先一直是ClearQuest的支持者,虽然用的是盗版,虽然用的是很老的2002和2003版。ClearQuest的功能就我感觉在各种缺陷管理软件中定制功能最为强大,而给非测试人员使用的ClearQuest Web客户端却是各种缺陷管理软件中最简易的。ClearQuest的强大定制功能,易于测试人员对缺陷管理流程和字段、页面等进行控制;Web端的易用(屏蔽一切与缺陷管理无关的内容)很利于开发人员的培训和使用。但是ClearQuest也有问题,一是软件安装太大且慢,二是需要使用SQL Server或Oracle数据库,三是配置起来过于麻烦,四是导出和备份都脱离了时代。其实我遇到的最大烦恼就是:ClearQuest的移植性不好。因为我换过几次的服务器,都需要很麻烦的步骤才能完成。感兴趣的,可以看看我曾经写过的关于ClearQuest的帖子,就能了解一些相关的内容。

我从3、4年前开始,就没有怎么使用过缺陷管理软件了,发现其实txt或Excel在小项目上也挺好用的,最多的时候7、8个测试人员,200多条缺陷,用Excel虽然麻烦些,但是也能很好的管理和记录缺陷。

但是近期有一个稍大些的项目,3个测试,10个开发,预期千条数量级的缺陷,再用Excel很明显不合适了,所以需要一个缺陷管理软件。因为服务器经常中病毒,所以随时的准备重新安装系统和相关软件,缺陷管理软件最好具有很高的移植性。

说下我们公司的网络环境,为了安全,我们公司的局域网完全和广域网进行物理隔离,无法上广域网,也无法使用邮箱。但是同事中很多人有笔记本,可以去专门的地方上网,局域网内电脑无法方便的升级操作系统和杀毒软件,笔记本又会从外网带来很多病毒,所以服务器常中病毒也是很正常的事情了。

上面的内容和技术没有太多的关系,只是简单介绍一下背景,因为下面的内容我的一些做法就和上面的背景和环境相关。

正式开始了。

luming 发表于 2011-10-29 16:57:53

(一)缺陷管理软件的选择和相关的软件环境
既然决定用缺陷管理软件,那么就面临一个问题,用哪个缺陷管理软件。
常见的缺陷管理软件,就是商业的QualityCenter(TestDirector)、Jira、ClearQuest,开源的bugzilla、mantis、bugfree、禅道等。
ClearQuest排除,原因序章已经进行说明。
TestDirector排除,第一是商业软件,第二局域网病毒太多,而TestDirector因为构架方面的原因很容易中病毒,第三我很久前用的7.2版的时候,有一些bug。
Jira,我去下载了一个**版,但是没有安装上,也许安装过程中需要联网和配置邮箱的缘故吧,放弃。
Bugzilla,有网络的情况下,我都没有信心能一次安装,在断网的条件下,还是放弃吧,而且bugzilla是perl开发的,也和现在的php主流不符,修改、和其他软件集成等比较费事。
剩下的就是mantis、bugfree、禅道了,都是php开发的缺陷管理软件。
Php集成环境软件很多,最后选择了EasyPHP,建议大家不要下最新的无法解包的EasyPHP-5.2.11版,建议大家下载5.2.10版,不需要安装可以直接解压,参照install_script.iss文档中的内容进行修改和配置,直接可以使用,这样有问题后,直接复制此easyphp目录就可以完成移植。
EasyPHP配置完毕启动成功后,没有问题了,就可以开始安装各个缺陷管理软件了。
去mantis、bugfree、zentao官网下载最新的版本,解压到www目录中,按照网上的说明进行相应的安装和配置。
Bugfree-2.1.3安装后,在首页有错误,去网上找了找,因为php.ini中allow_call_time_pass_reference参数的问题,修改后就好了。还有其他的问题,总出现Fatal error,对bugfree的软件质量印象不是很好。Bugfree本身支持测试用例管理和缺陷管理,从总体的感觉上,bugfree简陋且山寨,建议bugfree重新进行页面的设计,请美工人员进行页面的调整和配色。功能不提,界面上看,bugfree感觉是10年前的个人网站效果,没有任何的界面优化,条目的排列嘈杂混乱,后台管理简陋。
禅道按照Scrum开发方法设计,里面有需求、用例、TODO等内容,软件本身不予评价,但是功能太多了,我想用的仅仅是一个缺陷管理软件,也许按Scrum开发的团队使用禅道更合适。
剩下的就是mantis了,单纯的缺陷管理软件,但是可以和其他的软件进行集成,比如测试用例管理软件testlink。

luming 发表于 2011-10-29 16:58:02

(二)mantis的配置和开发环境
Mantis我用的1.2.5版,mantis的配置其实蛮复杂的,需要在config_inc.php中添加一些内容,统计图形那里也需要自己修改源码才能正确显示,但是网上都有相应的说明,很容易就可以找到。
建议对mantis感兴趣的,都看看doc目录下的administration_guide和developers两个文档,自己试验里面的参数和功能,对mantis的理解能加深不少。当然了,即使不深入了解,直接使用mantis也不会有什么问题。
因为后期做了mantis的开发,所以使用了php编译器Zend Studio,查看函数中的参数来源和在不同的函数之间跳转,跟踪代码很方便。
另外还用了UltraEdit和e-texteditor,UltraEdit主要用来在多文件中查找,当然Zend也能实现,但是很多时候未必查找zend工程内的东西。e-texteditor是很方便的代码查看器,简单的代码修改在e-texteditor中即可。
我进行mantis功能开发的时候,www目录中有3个mantis目录,一个是mantis,是正式上线使用的版本;一个是mantis1,是开发新功能用的,在zend中的工程就是mantis1目录;还有一个就是mantisBT,是原版没有修改过的,当修改参照。
当一个功能,在mantis1工程中开发完没有问题了,再在mantis中进行相应的部署;有问题了,和原版的mantisBT进行对照,很方便的。
在同期,我还配置了testlink,后期增加了dokuwiki,这是另外一个故事了,有时间再详细的说testlink和dokuwiki中的奥秘。

luming 发表于 2011-10-29 16:58:10

(三)mantis结构分析
其实这个应该放到最后的,因为只有在修改源码的时候,才会发现很多的东西mantis预先已经想到了,内容都在代码中,而不是在配置文件里面。所以很多时候,想要的功能,直接修改源码参数即可。等到后面,大家就可以具体的了解其中的内容了,此节仅仅对mantis的结构进行说明。
我本人不是开发出身,原先也不了解php,都是此次因为需要,才现看的php内容,好在不是需要开发一个不存在的系统,仅仅是在一个现有的体系下找到其中的节点和关键,这个就方便多了。
下面的内容,仅仅代表本人的一些看法,可能有不对的地方,大家可以随时指出,谢谢。
mantis的目录和文件很多,根目录下面的php文件主要都是功能页面,core目录中是需要的各种api函数文件,因为汉化的缘故,lang目录的strings_chinese_simplified.txt,也是我们关心的内容。
其实感觉mantis的结构安排不尽合理,根目录下面的大部分php文件,都应该放置到一个专门的目录,因为都是一些功能页面文件。而用户定义的内容,比如config_inc.php等,才应该放置在根目录或者专门的配置目录中,现在的安排显得很混乱,主次不清。
如果看过mantis的源码,会发现很多php中都首先引入
require_once( 'core.php' );
core.php是我们第一个需要分析的文件,把此文件分析完,应该如何让mantis按照自己的心意修改,我们也就了解了。

luming 发表于 2011-10-29 16:58:21

(四)core.php到底做了什么
下面的分析,我没有解释全部代码,只是挑选主要的说明mantis都在后面做了哪些魔法,感兴趣的可以直接去看完整的代码。
1.constant_inc.php
第45行:
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'core'.DIRECTORY_SEPARATOR.'constant_inc.php' );
constant_inc.php文件中定义了mantis中使用的各种常量。
2.custom_constants_inc.php
第50、51行:
if ( file_exists( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'custom_constants_inc.php' ) ) {
      require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'custom_constants_inc.php' );}
缺省安装mantis后,并没有custom_constants_inc.php文件,此文件在需要的时候由用户手工创建,主要是define用户自定义的常量值。按照基本的原则,没有绝对必要,不要修改mantis源码,mantis本身已经给你留下了接口文件,此custom_constants_inc.php文件就是。在custom_constants_inc.php中,不能用define定义在constant_inc.php已经定义过的常量。如果必须要修改,请在constant_inc.php中直接修改。
3. config_defaults_inc.php
第62行:
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'config_defaults_inc.php' );
    config_defaults_inc.php文件是mantis系统默认的参数配置文件。此文件和下面config_inc.php作用相同,但是config_defaults_inc.php是系统预设的,config_inc.php是用户自己定义的。
4. config_inc.php
第64-68行:
# config_inc may not be present if this is a new install
if ( file_exists( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'config_inc.php' ) ) {
      require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'config_inc.php' );
      $t_config_inc_found = true;
}
在安装或升级mantis的时候,mantis会自动把数据库连接等信息写到此config_inc.php文件中。用户需要自定义配置,也都是写入参数变量在此文件中。可以写入的配置变量参考doc目录内administration_guide的Chapter 5. Configuration章节。在根目录的config_inc.php.sample文件内也有一些相关的示例。总之,需要用户自定义的参数,就在config_inc.php中实现。
如果config_inc.php和config_defaults_inc.php参数有重复的情况,以config_inc.php中定义的为准。
5. custom_functions_inc.php
第245-248行:
$t_overrides = dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'custom_functions_inc.php';
if ( file_exists( $t_overrides ) ) {
      require_once( $t_overrides );
}
用户自定义的函数,请写入到此custom_functions_inc.php文件中。mantis安装后缺省没有此文件,需要的时候由用户手工创建。
6.其他
Core.php文件里面还定义了很多内容,比如载入core目录下面的各种api文件,定义时区,出否加载wiki等,但是和用户配置密切相关的,主要还是上面的5个文件。
7.总结
core.php主要加载mantis使用的资源和库文件,而且预留了用户的接口,主要就是变量config_inc.php、常量custom_constants_inc.php、函数custom_functions_inc.php,后两个文件在mantis默认安装后不存在,需要的时候由用户手工创建。在用户配置或开发的过程中,尽量不要修改mantis的原文件,优先使用此3个接口文件。
具体的示例,参考doc目录内administration_guide的Chapter 7. Customizing mantisBT。

luming 发表于 2011-10-29 16:58:32

(五)在config_inc.php中自定义配置
上面的都是分析,下面开始实践了,分两个部分,第一部分是通过修改config_inc.php配置文件,根据实际情况自定义需要的功能;第二部分是通过编写代码实现需要的功能。
先说一下我们的项目,项目的功能模块比较多,分批进行发布,随着开发进度,逐渐增加需要测试的模块,所以在mantis中建立一个主项目,主项目下根据需要建立各个子项目。
主项目仅仅表示下面的子项目属于此项目,并没有建立分类;版本在主项目定义,子项目不建立相关的子版本,统一使用主项目版本。
公司无法上广域网,而且没有内部邮箱,所以邮件相关的部分,我也都给清理了,需要邮件功能的,自己去查找相关配置。
以下内容没有特殊说明,都在config_inc.php中定义。
1.国际化
在config_inc.php中,如果通过install.php安装的,默认就有数据库相关的信息。
比如我的就是:
$g_hostname = 'localhost';
$g_db_type = 'mysql';
$g_database_name = 'mantis';
$g_db_username = 'mantis';
$g_db_password = 'mantis';
接着把mantis的默认语言设置为中文:
$g_default_language = 'chinese_simplified';
$g_default_language是很关键的参数变量,看源码就能清楚,在mantis中显示字段内容的时候,都是用lang_get()函数,lang_get函数会根据你设定的默认语言,找lang目录下对应的语言文件,比如$g_default_language 设定为'chinese_simplified'后,那么只要遇到lang_get(),就找lang/strings_chinese_simplified.txt文件中对应的变量,界面就相应显示为相应中文。
2.新建角色
不知道为什么,mantis缺省没有测试人员角色,只有报告员角色,但是报告员角色的权限比开发员低,也就是说,如果测试员设定为报告员角色,开发员因为权限更高,可以处理测试员的缺陷状态,比如直接关闭缺陷,我认为既然mantis主要给测试人员管理缺陷用的,那么测试人员的角色权限就应该在开发人员之上。
根据以上说明,创建新的测试人员角色。还有给匿名用户新建一个匿名用户权限。
在config_inc.php中,加入
$g_access_levels_enum_string = '5:匿名用户,10:复查员,25:报告员,40:修改员,55:开发人员,60:测试人员,70:经理,90:管理员';
在lang目录的strings_chinese_simplified.txt中,查找并修改
$s_access_levels_enum_string = '5:匿名用户,10:复查员,25:报告员,40:修改员,55:开发人员,60:测试人员,70:经理,90:管理员';
看清楚了,一个是$g_,一个是$s_,变量是不一样的。
在根目录新建custom_constants_inc.php文件,里面写入:
<?php
define( 'ANONYMOUS', 5 );
define( 'TESTER', 60 );
?>
custom_constants_inc.php其实不设定也不影响使用,但是如果需要修改角色相关的代码,最好按照mantis的习惯使用定义的常量,而不是常数。
分析一下,其实在config_defaults_inc.php中,存在系统预设的$g_access_levels_enum_string变量,所以我们在config_inc.php中用自定义的$g_access_levels_enum_string变量替换系统预设值。这样在使用过程中,就有了新的匿名用户角色和测试人员角色。
但是修改后,其实只相当于添加了5和60的角色,但是对应的默认语言(这里是中文)角色名称在lang/strings_chinese_simplified.txt的$s_access_levels_enum_string变量中没有定义,所以在使用过程中,就会出现@5@这样的角色。需要在相应的lang目录国际化文件中,对新添加的内容也定义相应的翻译。所有在程序中,遇到类似@60@这样的内容,都是因为变量没有定义相应的国际化语言名称。
另外,mantis设计的时候,编号不是随意的,高数值的很多情况下包含低数值的权限。比如10有提交缺陷的权限,那么10以上的其他角色,同样具备此权限,所以设计的时候要小心,一定要按照权限的高低进行排序设置。
3.严重性
Mantis预设的严重性项条目很多,感觉没有必要,按照我们公司的实际需要,定义四个就足够了。
在config_inc.php中定义:
$g_severity_enum_string = '30:建议,40:轻微缺陷,50:一般缺陷,60:严重缺陷';
在lang/strings_chinese_simplified.txt中,修改:
$s_severity_enum_string = '30:建议,40:轻微缺陷,50:一般缺陷,60:严重缺陷';
原有系统,50是默认的严重性,如果需要修改,可以在config_inc.php中定义:
$g_default_bug_severity = 40;
这样默认的严重性就是轻微缺陷。
4.缺陷发生频率
Mantis中默认的缺陷发生频率是70-REPRODUCIBILITY_HAVENOTTRIED(没有试验),我们把他默认设置为10-总是出现。
$g_default_bug_reproducibility = REPRODUCIBILITY_ALWAYS;
其中REPRODUCIBILITY_ALWAYS是在core/constant_inc.php中定义的常量,其实就是常数10。
5.缺陷状态
和上面的处理方法类似,在config_inc.php中定义:
$g_ status_enum_string = '10:新缺陷,30:暂不修改,40:不是缺陷,50:再次出现,80:已经修改,90:关闭';
在lang/strings_chinese_simplified.txt中修改:
$s_status_enum_string = '10:新缺陷,30:暂不修改,40:不是缺陷,50:再次出现,80:已经修改,90:关闭';
但是这么修改后,出现了一个问题,缺陷列表没有了缺陷状态对应的颜色,因为在config_defaults_inc.php文件内$g_status_colors数组中定义的键值和自定义的键值不同。
在config_inc.php中重新定义颜色键值:
$g_status_colors = array( '新缺陷'      => '#fcbdbd',      '暂不修改' => '#ffcd85',      '不是缺陷' => '#fff494', '再次出现' => '#c2dfff', '已经修改' => '#d2f5b0', '关闭'      => '#c9ccc4');
6.工作流
缺陷状态定义完毕后,定义工作流,可以使用管理员登陆,在管理->配置管理中定义相关的自定义字段、用户权限、工作流等内容。
其实在管理->配置管理->配置报告中,显示的就是已经定义的内容。愿意的话,你也可以直接在config_inc.php中定义,效果是相同的。
比如直接在config_inc.php中定义工作流:
$g_status_enum_workflow= array (
10 => '80:已经修改,30:暂不修改,40:不是缺陷',
30 => '50:再次出现',
40 => '90:关闭,50:再次出现',
50 => '80:已经修改,30:暂不修改,40:不是缺陷',
80 => '90:关闭,50:再次出现',
90 => '50:再次出现',
);
定义角色对缺陷状态的处理权限:
$g_set_status_threshold = array (30 => 55,40 => 55,50 => 60,80 => 55,90 => 60,);
还有很多,不详细说了,感兴趣的自己去看吧,反正就是需要,mantis后台配置的内容也可以在config_inc.php中直接定义。
7.其他
下面是其他一些在config_inc.php中可以定义的变量。
其实大家未必需要设置这么多的内容,我是因为实验各种参数,很多有用的就直接留下来了。
$g_enable_email_notification = OFF;//关闭邮件功能
putenv("TZ=Asia/Shanghai");       //定义中国时区
$g_complete_date_format='Y-m-d H:i:s';//日期格式
$g_delete_bug_threshold = MANAGER;    // 删除缺陷的角色权限
$g_max_file_size = 5000000;   //最大的附件容量,这个同时需要在php.ini中设置
$g_view_summary_threshold = VIEWER;   //最低允许查看统计角色
$g_show_realname = ON;   //在页面显示用户的姓名而不是帐号
$g_preview_attachments_inline_max_size = 2000000;   //支持预览用图片格式最大附件尺寸
$g_allow_anonymous_login = ON;             //是否支持匿名用户
$g_anonymous_account = 'anonymous';   //匿名用户的帐号,匿名登录后,为此帐号的权限
$g_show_timer = ON;      //在页面最下方,显示页面的载入时间
$g_default_home_page = 'view_all_bug_page.php';//登录后默认进入查看问题页面
$g_default_category_for_moves = 12; //这里是为了避免一个问题,移动缺陷的时候,默认的分类id设置为预设的全局分类General,但是我当时配置项目的时候,把此General分类给删除了,所以移动缺陷就会因为找不到分类而出现错误。这里我挑了一个在mantis_category_table表中存在的id。如果id=1的全局General分类存在,就不需要定义此项。
$g_enable_profiles = OFF;   //关闭平台配置,如果此项为on,那么提交缺陷的时候,就有一个平台配置供你选择
$g_allow_signup      = OFF;   //关闭注册帐号功能,需要邮箱才能注册,我们没有邮箱,就关闭了此项
$g_allow_file_upload= ON;   //下面的三项都是上传附件相关的,你可以不把附件保存在数据库中,而是保存在本地磁盘目录上
$g_file_upload_method = DISK;
$g_absolute_path_default_upload_folder = 'C://apache//www//mantis//upload//';
$g_show_project_menu_bar = ON;//在页面上方,显示项目直达链接
$g_time_tracking_enabled = ON;   //各项业务的处理时间,这个需要自己填写的,最后可以统计比如你处理缺陷用了多少时间等。
$g_wiki_enable = ON;    //下面的都是wiki相关的,我架设了dokuwiki
$g_wiki_engine = 'dokuwiki';
$g_wiki_root_namespace = 'mantis';
$g_wiki_engine_url = $t_protocol . '://' . $t_host . '/%wiki_engine%/';

luming 发表于 2011-10-29 16:58:45

(六)开发版本默认值功能
上一章用户定义的内容,都是通过系统自带的变量接口进行配置。但是一些内容,没有自定义的接口,怎么办?
mantis是开源软件,自己动手修改吧。
在提交缺陷的时候,有产品版本和目标版本,在处理缺陷的时候,有修正版本,这些版本都没有预设值,都需要自己手工选择版本,我们下一步就是通过自定义开发,给这些版本加上默认值。
1.自定义全局变量处理缺省版本
提交缺陷是根目录下的bug_report_page.php,处理缺陷是bug_change_status_page.php,在相关页面,鼠标右键->属性就能查到这些地址。
在zend中打开bug_report_page.php,找到缺省的设定版本的地方,产品版本在355行:
<?php print_version_option_list( $f_product_version, $t_project_id, $t_product_version_released_mask ) ?>
目标版本在395行:
<?php print_version_option_list() ?>
修正版本在bug_change_status_page.php文件的272-273行:
<?php print_version_option_list( bug_get_field( $f_bug_id, 'fixed_in_version' ),bug_get_field( $f_bug_id, 'project_id' ), VERSION_ALL ) ?>
三种版本都涉及到print_version_option_list()函数,跳转到print_version_option_list函数定义,在core/print_api.php中。
通过分析print_version_option_list函数,发现第一个参数就是显示默认值,那好办了,既然有默认值,自己定义默认值就可以了。
再次出动config_inc.php,在里面定义3个变量。
$g_product_version= 1.2;//产品版本
$g_target_version = 1.3;    //目标版本
$g_fixed_in_version = 1.3;   //修正版本
再把这些变量,填写为相应的print_version_option_list函数中第一个参数。
这次再看,新建缺陷或处理缺陷的时候,都自动填写上面设定的版本。
2.不通过全局变量处理
上面的方法确实有效,但是有一个问题,升级版本了,就需要再次修改这三个变量,而且不同的项目需要不同版本号的时候,全局变量的方法就无法处理。
我最开始的时候,想在数据库层处理这个问题,甚至在mantis_project_version_table表中建好了相应字段。我的想法是,在后台管理维护版本的时候,对应的版本都新建一个checkbox决定是否此项是默认值,接着读取变量写到print_version_option_list函数中。
很庆幸我很快就发现了新方法,因为上面的方法很麻烦,需要修改很多的内容,不是很值得。
在最开始使用的时候,版本的发布和过期选项我没有关注,都默认为空,但是后来终于想到了,可以通过这两个选项,控制默认的版本。
其他的就是翻类似的示例,看如何才能做到了。
比如target版本,在bug_report_page.php中添加代码:
$t_released = 0;//没有发布
$t_obsolete = false;    //没有过期
$t_versions = version_get_all_rows( $t_project_id, $t_released, $t_obsolete);
foreach ($t_versions as $t_version){
$g_target_version = $t_version['version'];
break;    //发现第一条就退出
}
接着就是设定$g_target_version变量到目标版本对应的print_version_option_list函数中当默认值。
产品版本和修正版本也做类似的处理,产品版本对应参数是:
$t_released = 1;//已经发布
$t_obsolete = false;    //没有过期
修正版本是:
$t_released = 0;//没有发布
$t_obsolete = false;    //没有过期
这次,终于可以随着项目变化自动填写默认值了,仅仅需要每次添加新版本的时候,设定是否发布和是否过期。
3.处理修正版本默认值
现在可以正确填写需要的默认版本号,产品版本和目标版本没有什么问题,但是到修正版本那里,出现了问题。
处理缺陷的时候,修正版本号每次都自动填写没有发布的第一个版本,但是原先处理过的缺陷,再次验证的时候,修正版本很多情况下应该读取原有的而不是未发布的。修正版本的正确处理方法应该是已经存在修正版本的情况,读取已有的修正版本,没有的时候,才需要赋予默认值。
下面就是处理方法,在bug_change_status_page.php文件,查找并替换代码为以下内容:
<!-- Fixed in Version -->
<?php $t_fixed_in_version = bug_get_field( $f_bug_id, 'fixed_in_version' ); ?>
<tr <?php echo helper_alternate_class() ?>>
            <td class="category">
                  <?php echo lang_get( 'fixed_in_version' ) ?>
            </td>
            <td>
                <select name="fixed_in_version">               
                        <?php if ($t_fixed_in_version ) {
                         print_version_option_list( $t_fixed_in_version, bug_get_field( $f_bug_id, 'project_id' ), VERSION_ALL );                        
                        } else {
                         print_version_option_list( $g_fixed_in_version,      bug_get_field( $f_bug_id, 'project_id' ), VERSION_ALL );
                        }?>                                                                                 
                </select>
            </td>
</tr>
其中$t_fixed_in_version 是已经录入过的修正版本变量,$g_fixed_in_version是上一节中通过版本的发布和过期选项确定的修正版本变量。
按照上面的修改,我们实现了修正版本存在就读取存在的,不存在就给他默认值。
一切都会变好的。
4.发现共性,进行重构
上面的版本相关代码,写到了bug_report_page.php和bug_change_status_page.php文件中,但是主体内容其实是一样的,都是根据不同的project_id取得版本,接着取满足条件的第一个版本,返回版本变量。
开发中的一条基本原则就是不要重复自己,同样的代码写到了两个以上的地方,就有重构的需要了。
那么我们就重构,提取相同的代码为公共函数。
在根目录创建custom_functions_inc.php文件。
里面写入提取的函数:
<?php
function custom_version($project_id,$t_released ,$t_obsolete) {
foreach (version_get_all_rows( $project_id,$t_released,$t_obsolete) as $t_version){
    $t_custom_version = $t_version['version'];
    break;
}
return $t_custom_version;
}
?>
在bug_report_page.php中,版本调用就成了下面的样子。
修改产品版本相关代码:
<?php print_version_option_list( custom_version($t_project_id, 1, false), $t_project_id, $t_product_version_released_mask ) ?>
其他版本处理方法类似。
继续分析,自定义函数中的$t_obsolete一直都是false,既然都是false,那么此参数出否必要呢?查看调用的version_get_all_rows函数定义,默认$p_obsolete = false,那么此参数就是可以去除的。
$t_released变量取值1、0都是硬编码,应该使用常量代替,在core/constant_inc.php中发现,mantis已经帮你定义好了。
# Versions
define( 'VERSION_ALL', null );
define( 'VERSION_FUTURE', 0 );
define( 'VERSION_RELEASED', 1 );
所以最终在custom_functions_inc.php中定义的函数是:
<?php
function custom_version($project_id,$t_released= VERSION_ALL) {
foreach (version_get_all_rows( $project_id,$t_released) as $t_version){
    $t_custom_version = $t_version['version'];
    break;
}
return $t_custom_version;
}
?>
在bug_report_page.php中,产品版本:
<?php print_version_option_list( custom_version($t_project_id, VERSION_RELEASED), $t_project_id, $t_product_version_released_mask ) ?>
目标版本:
<?php print_version_option_list(custom_version($t_project_id, VERSION_FUTURE)) ?>
在bug_change_status_page.php文件中,把上一节中的代码:
print_version_option_list( $g_fixed_in_version,      bug_get_field( $f_bug_id, 'project_id' ), VERSION_ALL );
替换为:
print_version_option_list(custom_version($t_project_id, VERSION_FUTURE),      bug_get_field( $f_bug_id, 'project_id' ), VERSION_ALL );
终于觉得一切都hold住了。
5.对版本更本质的分析
上面的做法,只是完成了预定的功能,就是给一个默认版本号。但是我们可以更进一步想想,版本号到底有什么用?当然了,没有必要上升到哲学的高度,我们仅仅是测试员而已,只需要了解自己手里的工具,让他更有力。
在后台管理版本的时候,版本有两个选项:已发布、已过期。
而程序中调用版本的地方有三个,产品版本、目标版本、修正版本。
我们需要考虑的是:mantis为什么这么设定,这么设定有什么意义。
下面是我认为的三个版本的含义:
产品版本:当前测试软件的版本。
目标版本:预期把缺陷处理掉的版本。
修正版本:真正解决掉缺陷的版本。
其中产品版本一定是已经发布的,目标版本是没有发布的,修正版本有可能发布、也有可能没有发布。
mantis有两个功能模块:
变更日志(Changelog):记录项目在各个不同的版本已经处理的缺陷。根据修正版本进行记录,只记录最终状态为已解决和已关闭的缺陷。
路线图(Roadmap):在预期的目标版本是否真正处理了缺陷,给一个项目已经处理缺陷的百分比。根据目标版本进行分类,最终状态为已解决和已关闭的缺陷才计算为已经处理的缺陷。
变更日志和路线图功能需要使用的时候,都必须设定相应版本。
例如:一个问题,发现在1.2版本,目标1.4版本,关闭在1.5版本。相应的变更日志中,在1.5版本就记录一条状态为关闭的记录;在路线图中,1.4版会记录此问题关闭并且算已解决问题。
所以说,mantis之所以设计为三个版本,是为了相关的功能需要。
如果大家认为不需要使用变更日志和路线图功能,三种版本没有必要全部填写。
6.修正版本
通过上面的分析,我们知道,产品版本不会变化,目标版本根据需要改变(例如目标版本预期1.2版,但1.2没有解决此缺陷,可以重新设定目标版本,也可以不理会,看实际需要),修正版本不同,有可能开始设定的和最终修正的不一样。
设计一个场景:在1.2版本测试员发现一个缺陷,在开发人员处理的时候,修正版本是1.3,但是测试人员在发布的1.3版测试发现,此问题没有修改,实际现在修正版本就已经不是1.3了,需要在后续处理的时候,我们自己选择是1.4甚至1.5版本才真正修复了此问题。
啊,上面做了那么多的工作,我们还是需要手工修改版本,太不nice了,那么我们就想方设法的自动处理修正版本。
注意:下面的内容,不算是好的处理方法,有些geek的意味,通常大家没有必要这么极端。
既然修正版本可能过期,那我们就干脆把修正版本自动设置为当前已发布版本,这样就不存在过期的问题了。
但是有一个问题,只有已经修改之类缺陷处理的时候有版本号,关闭等状态处理的时候页面没有版本号项,这样如果每次强制自动调用最新已发布版本为修正版本,有可能造成1.2版修正了,1.3版关闭的时候因为无法选择1.3修正版本在数据库中记录的修正版本还是原有的1.2版。
所以我们需要在缺陷处理页面开放修正版本项,在任意的处理状态都可以使用修正版本。
修改bug_change_status_page.php文件,查找并修改修正版本为下面内容,主要就是把状态判断的代码屏蔽,并且设定当前已发布版本为修正版本:
<?php
# if ( ( $f_new_status >= $t_resolved ) ) {
      $t_show_product_version = ( ON == config_get( 'show_product_version' ) )
                || ( ( AUTO == config_get( 'show_product_version' ) )
                                        && ( count( version_get_all_rows( $t_bug->project_id ) ) > 0 ) );
      if ( $t_show_product_version ) {
?>
<!-- Fixed in Version -->
<tr <?php echo helper_alternate_class() ?>>
      <td class="category">
                <?php echo lang_get( 'fixed_in_version' ) ?>
      </td>
      <td>
                <select name="fixed_in_version">
                        <?php print_version_option_list( custom_version( $t_bug->project_id, VERSION_RELEASED), bug_get_field( $f_bug_id, 'project_id' ), VERSION_ALL ) ?>
                </select>
      </td>
</tr>
<?php }
      #}
      ?>
这次再看,每次处理状态的时候,版本号都随着当前版本变动,不会出现过期的情况了。
大概版本处理到这种程度,可以改进的地方应该不多了。
一切都在掌控中。

luming 发表于 2011-10-29 16:58:58

(七)对mantis做的其他修改
此章的内容,都是根据项目的实际需要通过修改源码而不是配置的方式实现相应的功能。大家使用过程中,可能不会遇到此类问题,那就没有必要修改mantis源码。
1.查看问题的子项目版本号
看过前面内容,你就了解,我建立了一个主项目,下面有几个附属子项目,版本号都设定在主项目内,子项目直接使用主项目版本号。
但是在子项目内,查看问题(view_all_bug_page.php)页面,过滤条件中版本相关的三项(产品版本、目标版本、修正版本)都只有子项目本身的版本,而没有显示主项目的版本号。其实mantis如此设计也可以,但是具体到此项目,就不方便了。
我们就处理一下此问题,让子项目也可以看到主项目版本。
在core/filter_api.php中,修改3689行、3703行、3717三行代码为:
<?php print_version_option_list( $t_filter, /* projectId */ null, /* released */ VERSION_ALL, /* leadingBlank */ false, /* withSubs */ false )?>
这样在子项目的时候,也可以在查看问题页面看到主项目版本了。
2.在新窗口中打开wiki
我安装了dokuwiki并和mantis相关联,所以mantis页面上有维基标签链接,但是点击此链接,dokuwiki在当前页面打开,而我更希望维基在新窗口打开。
在core/html_api.php文件,770行修改为:
$t_menu_options[] = '<a href="' . helper_mantis_url( 'wiki.php?type=project&amp;id=' ) . $t_current_project . '" target="_blank">' . lang_get( 'wiki' ) . '</a>';
根目录bug_view_inc.php文件,220行修改为:
print_bracket_link( $tpl_wiki_link, lang_get( 'wiki' ), true );
3.子项目的变更日志和路线图
这应该是mantis的一个缺陷,我在mantis缺陷库中找到的处理方法。当存在子项目的时候,子项目没有显示变更日志和路线图,在相关功能中是空白页面。
修改core/version_api.php,屏蔽406-415行内容:
/*
      if( isset( $g_cache_versions_project[ (int)$p_project_id ] ) ) {
if( !empty( $g_cache_versions_project[ (int)$p_project_id ]) ){
                foreach( $g_cache_versions_project[ (int)$p_project_id ] as $t_id ) {      $t_versions[] = version_cache_row( $t_id );
            }
                return $t_versions;
          } else {
                return array();
          }
      }
*/
4.修改变更日志和路线图的样式
变更日志和路线图,页面太简陋了,都是在白背景上显示内容。
给相关的内容加上table和颜色,看着感觉就好多了。
首先在custom_constants_inc.php中,添加颜色常量,以后换颜色直接修改这些常量就可以:
define('TITLE_COLOR', '#c8c8e8');
define('TEXT_COLOR', '#e8e8e8');
define('RESOLVED_COLOR', '#c8e8e8');
修改changelog_page.php,在71行添加table:
echo '<table bgcolor = '. TITLE_COLOR .'><td>';
echo '<br /><span class="pagetitle">', string_display_line( $p_project_name ), ' - ', lang_get( 'changelog' ), '</span><br />';
echo '</td></table>';
294-314行修改为以下内容:
echo '<tablewidth="100%">';
for ( $j = 0; $j < count( $t_issue_set_ids ); $j++ ) {
      $t_issue_set_id = $t_issue_set_ids[$j];
      $t_issue_set_level = $t_issue_set_levels[$j];
    echo '<tr bgcolor= '. TEXT_COLOR .'><td>';
      helper_call_custom_function( 'changelog_print_issue', array( $t_issue_set_id, $t_issue_set_level ) );
      echo '</td></tr>';
}
echo '</table>';
if ( $t_issues_resolved == 1 ) {
      echo '<table><tr bgcolor = '. RESOLVED_COLOR .'><td >';
      echo "[{$t_issues_resolved} " . lang_get( 'bug' ) . ']';
      echo '</td></tr></table>';
      echo "<br /><br />";
} else if ( $t_issues_resolved > 1 ) {
      echo '<table><tr bgcolor = '. RESOLVED_COLOR .'><td >';
      echo "[{$t_issues_resolved} " . lang_get( 'bugs' ) . ']';
      echo '</td></tr></table>';
      echo "<br /><br />";
}
在roadmap_page.php文件中,修改56-58行:
echo '<table bgcolor = '. TITLE_COLOR .'><td>';
echo '<br /><span class="pagetitle">', string_display( $p_project_name ), ' - ', lang_get( 'roadmap' ), '</span><br />';
echo '</td></table>';
修改301-316行:
echo '<tablewidth="100%">';
for ( $j = 0; $j < $t_count_ids; $j++ ) {
      $t_issue_set_id = $t_issue_set_ids[$j];
      $t_issue_set_level = $t_issue_set_levels[$j];
    echo '<tr bgcolor= '. TEXT_COLOR .'><td>';
      helper_call_custom_function( 'roadmap_print_issue', array( $t_issue_set_id, $t_issue_set_level ) );
      echo '</td></tr>';
}
echo '</table>';
if ( $t_issues_planned > 0 ) {
      echo '<table><tr bgcolor = '. RESOLVED_COLOR .'><td >';
      echo sprintf( lang_get( 'resolved_progress' ), $t_issues_resolved, $t_issues_planned, $t_progress );
      echo '</td></tr></table>';
      echo '<br /><br /><br /><br /><br /><br /></tt>';
}
修改后,再看变更日志和路线图,感觉舒服多了。
5.直接登录wiki
在mantis中架设了dokuwiki,设置dokuwiki用户由mantis托管,所以直接打开dokuwiki是匿名用户,而且没有登录选项,只能通过mantis跳转才有相应账号权限。我们就通过编写代码,在仅仅想使用维基的情况下,在mantis的登录页面直接用mantis账号登录wiki。
在login_page.php中,154行后添加如下内容:
<tr class="row-1">
      <td class="category">
                <?php echo lang_get('wiki') ?>               
      </td>
      <td>
      <input type="checkbox" name="wiki_login" value="on" />      
      </td>
</tr>
修改login_page.php 文件,57行后修改为:
if ($_POST['wiki_login'] == 'on'){                  print_header_redirect('/'.$g_wiki_engine,true,false,true);                     
} else {
      print_header_redirect( $t_redirect_url );      
}
最后的效果是这样,可以直接用mantis的账号登录dokuwiki:

luming 发表于 2011-10-29 16:59:42

(八)总结
不知道有几个人,能完整的看完我写的这个系列,断断续续的写了一周多,中间对自己的mantis也重新整理了一下,原先不是很规范的地方,按照文中所写规规矩矩的来。其实最开始很多地方,我图省事都直接写值而不是定义变量或常量的。
这个系列,仅仅是我对使用mantis这几个月的总结,我看过很多人写的mantis安装配置文章,里面都仅仅说如何配置mantis完成需要的功能。而我这个系列的文章,希望告诉大家,为什么按照别人说的配置下来,mantis就能相应改变,大家如果能从知其然到知其所以然,也就不枉费我花费这么多的精力了。
个人的文笔有限,很多事情我都写的很细而且反复强调,这也许是测试人员的通病,描述问题的时候更细更细更细,省得开发人员找麻烦。了解mantis的人可能会觉得我说的过于繁琐,但是我这个系列是给希望了解mantis的初学者看的,高手可以直接看代码,比我文中说的更详细和准确。
其实觉得mantis的结构安排不尽合理,很多的内容过于绕,比如编辑缺陷时候的页面是bug_update_page.php,但实际bug_update_page.php中没有内容,真正的页面在
bug_update_page.php-> bug_update_advanced_page.php。也许是因为mantis已经开发很久了,原先很多的旧版本文件都留下了。函数也一样,很多内部变量都要绕几个圈子。但是mantis确实考虑到了很多的情况,看过上文就知道,很多内容不需要大改,mantis尽可能的把函数参数接口都设计好了,可以根据需要由用户直接调整。
大概就是这些了,文章虽然检查了几遍,但是个人不敢保证里面是否还有问题。
发现此文问题或想和我更深入探讨mantis的朋友,可以使用以下联络方式:
Email:fangu002@163.com
51testing帐号:luming

Over。
再次感谢有耐心看完全文的的人。

pyp(鹿鸣)
                                          2011年8月26日星期五

luming 发表于 2011-10-29 16:59:53

本帖最后由 luming 于 2014-9-24 06:43 编辑

(九)补充一
嗯,写完后,又修改了一些内容,做下记录。
1.路线图扩展
上面分析版本的时候,说过了,根据修正版本,记录相关的路线图,但是在路线图中,只记录没有发布的版本,我想最好能看到所有版本的路线图,因为上面处理的时候,修正版本一直在不停的改变。
注释掉roadmap_page.php文件中下面的内容:
      //                if ( $t_version_row['released'] == 1 ) {
      //                        continue;
      //                }
这次没有过期的版本在路线图中就都可以看到了。
其中有两个小问题,一是版本排序是从小到大,但是感觉从大到小更好些;二是所有的版本都是待发布,其中大部分都是已发布的版本。
上面问题的解决,等我有时间再仔细看看代码。
2.添加注释
缺陷有处理流程,但是开发人员在处理的时候,很多时候都乱选缺陷状态,结果到测试这里,都无法处理。
所以我们的测试人员提出了,在页面上添加注释,提醒开发人员选择正确的缺陷状态。
Ok,有需求了,那就干活吧。
在bug_view_inc.php文档中,查找添加下面的内容,中间棕色部分是我添加的:
if ( $tpl_bottom_buttons_enabled ) {
      echo '<tr align="center"><td align="center" colspan="6">';
      html_buttons_view_bug_page( $tpl_bug_id );
      echo '</td></tr>';
      }
echo '</table>';
      
echo '<tableclass="width100" cellspacing="0"><tr bgcolor= '. TEXT_COLOR .'><td>';
echo '<p/><p/>';
echo '<font color = red>已经修复</font>的问题,状态改为:已经修改;测试人员提交的问题<font color = red>不是错误</font>,状态改为:不是缺陷;问题<font color = red>是缺陷</font>但是<font color = red>暂时不处理</font>或<font color = red>需求不明确</font>的,状态改为:暂不修改。<p/>';
echo '请正确选择缺陷处理状态,暂不修改请写明原因,谢谢。';
echo '</td></tr>';      
echo '</table>';               

# User list sponsoring the bug
include( $tpl_mantis_dir . 'bug_sponsorship_list_view_inc.php' );
其中class="width100"是根据css文件中的table定义,以和其他的table保持一致,TEXT_COLOR是原先曾经定义的常量,也可以直接录入颜色值。
在查看缺陷详细页面效果如下图:

3.自定义字段的提示
自定义了两个新的选项,一个是在提交缺陷的时候,自定义枚举类型字段:
缺陷类型:|数据|界面|功能|提示|性能|配置|未知
在处理缺陷的时候,自定义枚举类型字段:
    缺陷来源:|需求|构架|设计|编码|集成|测试|维护|翻译|外部
还是老问题,测试人员好解决,直接告诉应该选择哪个,但是开发人员还是喜欢乱来,那么就还是给相应的提示。
在bug_change_status_page.php中,查找添加下面的内容:
      <?php
                        print_custom_field_input( $t_def, $f_bug_id );
                ?>

      <?php if (lang_get_defaulted( $t_def['name'])=='缺陷来源') {
      echo '       引入缺陷的阶段或缺陷根本发生原因的阶段</td>';
      }?>

</tr>
<?php
            } #custom_field_has_write_access( $t_id, $f_bug_id ) )
中间的棕色部分是新添加的内容,如果有别的内容,也可以类似处理,就是判断一下名字,在后面添加内容而已,效果如下图:

4.添加用例链接 2013.8.11
我使用testlink管理用例,在testlink中可以连接到mantis,但是mantis中没有testlink的链接,我这里在上面的链接中加入testlink

core/html_api.php文件中,查找
# Manage Users (admins) or Manage Project (managers) or Manage Custom Fields 行的前面加上

$t_menu_options[] = ' <a href="/testlink/index.php" target="_blank">用例</a>';

5.必须录入问题注释 2014.9.22

新的一期来了。近期加了一些小改动,但是没有大的变化,就一直没有记录更新。今天继续。
在变更状态的时候,有“添加问题注释”(Add Notes),我都花手段给加上了红*,上面也添加提示必须要填写,但是开发人员就是不填写注释。
那行,你不添加是不,你不添加我就不让你过去。下面就是这样的手段。

找到bug_update.php文件。
添加
<code>
$t_bugnote_text = gpc_get_string('bugnote_text');

if( is_blank( $t_bugnote_text ) ) {
    error_parameters( lang_get( 'add_notes' ) );
    trigger_error( ERROR_EMPTY_FIELD, ERROR );
}
</code>

这样不填写问题注释的时候,就会提示“APPLICATION ERROR #11 字段“添加注释”是必须填写的,不能为空白,请重新填写。”

306664257 发表于 2011-11-3 16:49:29

斑竹辛苦,正在学习mantis,mark一下

fineapple 发表于 2011-11-4 15:34:51

学习了,回去试试,有问题再来请教 :)

kaixinle 发表于 2011-12-27 10:54:41

请教您一个问题:如何恢复mantis删除的bug单?前几天对mantis上的分类重新整理,删除原有分类后,bug单也没了,请问一下应该怎么恢复呢???

luming 发表于 2011-12-27 17:45:45

回复 13# kaixinle
查数据库,我记得应该是mantis_bug_table表,看记录是否存在,存在的话,把分类项填一个现有的分类就可以了。

archonwang 发表于 2011-12-28 15:28:01

辛苦了。此贴甚好。

经验这回事情,不在于你干了多少,做了多久,而在于是否经常性总结。

yanzs0120 发表于 2011-12-30 13:39:27

mantis 是开源的,所以不错,用起来还是比较方便的。

306664257 发表于 2012-1-4 12:05:15

Mark,正在学习中!好帖必须顶!

yangxu0601 发表于 2012-3-22 10:04:42

写得很不错,学习了。

现在正为mantis发邮件问题而苦恼!!

hlq0514 发表于 2012-4-10 17:18:00

请问下,这么修改 优先级下的子选项,比如自定义一些优先级

luming 发表于 2012-4-10 18:00:37

请问下,这么修改 优先级下的子选项,比如自定义一些优先级
hlq0514 发表于 2012-4-10 17:18 http://bbs.51testing.com/images/common/back.gif

第5部分就是说这个问题的。你在config_defaults_inc.php中可以找到优先级,你可以重新定义。还要在lang/strings_chinese_simplified.txt修改对应的中文。
页: [1] 2 3
查看完整版本: Mantis解析