基于自定义向导的C++单元测试环境自动化配置

2017-06-13   出处: 腾讯移动品质中心TMQ  作/译者:姜宏维  

导语相信使用过Visual Studio的小伙伴都感受过VS向导的强大,通过应用程序向导,我们可以很方便地搭建应用程序,通过代码向导,可以大大提高我们编写代码的效率。但VS的内置向导模板有时候并不能满足我们一些特殊场景的需求,比如基于第三方库的程序,每次都要手动配置一堆配置,编写重复的框架代码,Copy-Paste大法又容易犯错。本文介绍了Visual Studio扩展自定义向导的完整步骤以及核心的技术要点,通过自定义向导,可以简化许多场景下的环境配置以及框架搭建操作。


一、从向导的向导说起


VS的自定义向导,同样可以通过VS本身来开发,而且VS也为向导工程提供了向导来生成所需要的基本框架(有点类似编译器的自举)。打开VS,点击File->New Project,选择Visual C++节点(本文主要讨论C++项目的自定义向导,VS同样支持其他语言自定义向导),点击Custom Wizard,设置好相关的信息后,点击Finish,一个向导工程就创建完毕了

这时,我们打开一个新的VS,再打开New Project页面,会发现Templates列表中已经出现了我们自定义的向导:

二、自定义向导的编写


当前的向导已经具备创建一个空的工程的能力,我们还需要了解很多相关内容才能编写出功能强大的自定义向导。

下图显示了一个命名为MyWizard的向导工程的默认文件:

总体来说,这些文件会在VS的向导引擎中被用到,大致流程及相关文件如下:

文件有点多,我们一个一个介绍。

HTML Files:这个文件夹中有一个命名为default.htm的文件,这个文件定义了我们的向导与用户的交互对话框,VS中使用Design预览下这个htm文件(VS2005的预览功能实在太差,截图使用的是VS2015的预览窗口):

这个对话框,其实是一个基于HTML的Dialog,上面的控件与布局,都是通过HTML来描述的,默认生成的页面效果如下图:

通过defaul.htm,我们可以提供一些自定义选项给用户来自定义自己的工程配置(比如各种工程配置,生成的文件的名字等各种VS能够提供的几乎所有功能),对于熟悉HTML的同学,编写这个文件几乎毫无障碍,默认的htm文件已经给出了很全面的范例(不过还是要吐槽一下布局,table套table,看得人眼花缭乱,还好VS有强大的设计编码拆分窗口)。如果你的向导不需要用户自定义配置,那么default.htm不是必须的,在建立向导工程时,去掉User interface的勾选框,这个default.htm就不会生成,用户在New Project点击OK的时候,会直接执行后边的工程创建操作。

需要特别提到的是,在HTML文件中,可以使用<SYMBOL></SYMBOL>声明一些符号:

	

<SYMBOL NAME='SAMPLE_CHECKBOX' TYPE=checkbox VALUE=true></SYMBOL>

这些符号对应了相关控件的默认值,比如NAME为SAMPLE_CHECKBOX的SYMBOL定义了ID为SAMPLE_CHECKBOX的值为TRUE

	

<INPUT CLASS="CheckBox" TYPE="checkbox" ID="SAMPLE_CHECKBOX">

 那么这个勾选框控件在展示的时候就是默认勾选的状态。

后边在脚本文件中,我们可以通过相关的语句去读取这个值(详见后边的Script Files的介绍:var bCheck= wizard.FindSymbol('SAMPLE_CHECKBOX');用户勾选了Sample checkbox,会返回true,否则就返回false。

在这里我们可以编辑HTML来设置GTEST相关的一些选项,比如是否生成测试类的某些方法以及配置、属性继承:

Image Files:这个目录可以放置我们在向导default.htm中使用的自定义图片资源。注意到最外边有一些gif文件,这些是生成的默认向导工程所使用的图片文件。

Miscellaneous Files:这里边比较重要的几个文件是:.ico.vsdir.vszTemplates.inf文件。

(1).ico文件其实就是我们在New Project对话框看到的模板项目的图标,替换这个文件就可以改变在New Project对话框中的图标。

(2).vsdir是一个纯文本文件,文件内容如下:

	

GoogleTestProject.vsz| |GoogleTestProject|1|TODO: Wizard Description.| |6777| |GoogleTestProject.

 .vsdirVisual Studio Shell程序与向导项目中的项之间提供路由服务的文本文件,其中包含了很多的字段,以 “|”分隔(微软官方文档VSDir 文件组件给出了每个字段的含义)。其中,我们一般只需要关注TODO的部分和最后一个字段,TODO这个是我们的向导在New Project界面显示的描述字段,最后一个字段是工程的默认名称Name。

(3).vsz文件标识向导引擎并提供上下文和可选的自定义参数,它也是一个纯文本文件:

	

VSWIZARD 7.0 Wizard=VsWizard.VsWizardEngine.8.0 Param="WIZARD_NAME = GoogleTestProject" Param="ABSOLUTE_PATH = D:\Code\VSWizard\GoogleTestProject\GoogleTestProject" Param="FALLBACK_LCID = 1033"

头两行表示了向导版本号以及向导引擎的版本,不同版本不能混用,对于VS2005为:

	

VSWIZARD 7.0 Wizard=VsWizard.VsWizardEngine.8.0

 VS2015则是:

	

VSWIZARD 7.0 Wizard=VsWizard.VsWizardEngine.14.0

 自定义参数的格式为:

	

Param="<PARAM_NAME> = <PARAM_VALUE>"

 VS中本身会有一些内置的参数,具体可查阅微软官方文档:向导 .vsz 文件中的自定义参数。

WIZARD_NAME这个定义了向导的名称,在向导PATH未指定的时候,向导会根据这个名字取查找相关文件;

ABSOLUTE_PATH告诉引擎在什么位置去查找相关的向导文件,一般在开发阶段会使用这个ABSOLUTE_PATH方便调试,后边部署的时候需要删掉或者使用RELATIVE_PATH(相对路径);

FALLBACK_LCID是指本地化相关的配置,1033表示英文(我用的是英文版VS所以这里是1033),2052表示简体中文,后边部署的时候会讲到相关的本地化问题。

        (4)Templates.inf文件用来配置哪些文件需要拷贝到工程中,它也是一个纯文本文件,我们可以在Template Files下新建一些我们想要拷贝到新工程的文件,然后在Templates.inf中添加新行就可以了。inf文件本身也是一个模板文件,可以使用模板指令(如[!if] [!else]等,参见后文Template Files介绍)。

Script Files:前面说到htm文件定义了与用户的交互界面,那么default.js便是用来定义相关的事件响应逻辑,当用户在自定义配置对话框点击完成之后,后边的处理都会交给这个js文件来完成,我们重点关注OnFinish这个函数,用户点击完成之后,这个函数会被调用,默认生成的代码。很清晰,首先,通过wizard(向导的内置对象)获取用户设置的工程路径以及工程的名字,然后调用CreateCustomProject创建工程(实际上是创建了一个基本的.vcproj文件),然后添加相关的配置,设置文件分类(定义哪些属于头文件、源文件、资源文件),然后根据.inf文件渲染创建一个临时的.inf文件,将Template Files中的文件拷贝到我们新建的工程中,删除临时的.inf文件,最后保存新建的工程。

第一眼去读这些函数,你会觉得很莫名其妙,凭空就能使用的对象和函数是从哪来的?其实,对于使用js来操作VS,是属于VS扩展模型的一部分,它底层基于COM,使用C++、C#、JS等都能够进行操作(各类VS扩展插件都是基于该模型编写),具体参考微软文档:扩展 Visual Studio 环境

在VS安装目录下,比我的机器上的VS2005英文版:C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCWizards\1033\common.jsC:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCWizards\1033\Script.js。文件中封装了大量的相关函数,可以直接在default.js中使用,其实在htm文件中,我们可以看到,它们会被提前加载进来:

VS向导的向导为了示范如何使用wizard、dte等内置对象,所以生成的default.js比较复杂,其实对于一般的需求,使用Common.js中的函数就可以完成绝大部分功能,我重写了一下,以下代码框架足够使用:

通过查阅Common.js中的代码,我们可以学习到更多相关的对象以及函数的使用,也可以了解到inf文件一些常见的指令前缀(比如CopyOnly、OpenFile等),这里就不展开说明了。

Template Files:这个文件夹存放了我们向导需要拷贝到新工程的所有模板文件,它们可以是.h.cpp代码文件,也可以是.ico.txt.rc等资源文件,任何想要生成在工程中的文件都可以放到这里,Template Files一般需要配合Templates.inf来完成相关的渲染与拷贝操作。因为用户创建一个工程的时候,难免会带上一些自定义的参数,比如使用过MFC向导的同学应该知道,我们可以指定生成的类的文件名、是否使用ATL、是动态链接还是静态链接到MFC库、使用多字节字符集还是使用Unicode字符集等,这就使得模板文件不可能是一成不变的,文件的内容必然会有变量然后有类似宏替换的操作,VS向导引擎提供了一些模板文件和Templates.inf文件中可以使用的模板指令,来完成这些需求

比如我们编写一个GTEST测试类的向导,用户可以有选择的生成或者不生成一些方法,那么模板文件可以这样编写:

[!output PROJECT_NAME] 是一条输出语句,表示测试类的名称就是工程的名字。[!if GENERATE_SETUP_TEARDOWN] [!endif] 是一条判断语句,中间包含了SetUp()/TearDown()方法,如果GENERATE_SETUP_TEARDOWN这个符号(可以在htm文件中定义)为true,那么代表需要生成SetUp()/TearDown()成员函数,反之就不会生成该成员函数,对于SetUpTestCase()和TearDownTestCase()同理。


三、自定义向导的调试


 向导工程其实没有编译生成的概念,因为所有的文件都是以脚本形式存在,向导的调试主要集中在default.js文件,VS强大的调试功能在此时同样能够派上用场,官方的文档对于JS调试给出的方案其实是针对ASP.NET下的,所以那些所谓的在IE中去除禁用调试选项以及设置调试cookie纯粹是在误导(我也不知道为什么微软要把这些帮助链接关联在一起,也许是机器人干的吧)。

其实调试向导很简单,新开一个VS,然后在编写向导的VS中点击Debug->Attach to Process,Attach to类型选择Script(这一步很关键,选错类型断点会无效):

进程选择新开的那个VS进程:

点击Attach,即可关联调试进程,然后在default.js中掐断点,在被调试VS中新建我们的GoogleTestProject类型工程,点击OK后,如果有断点触发,我们可以在编写向导的VS中查看各种调试信息,比如变量、函数栈等,后续的操作就跟平常调试代码一样了:

四、自定义向导的部署


      自定义向导的部署本质上只需要拷贝文件到相应的目录,假设VS(以VS2005英文版为例)安装在以下目录:

	

C:\Program Files (x86)\Microsoft Visual Studio 8\

那么相应的向导文件存放下以下两个目录下:

	

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcprojects。 C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCWizards。

 vcprojects存放.ico.vsdir.vsz文件,这个目录下可以新建子目录,新建的子目录会在New Project对话框中表现为一个新的分类。

例如我们将GoogleTestProject.ico、GoogleTestProject.vsdir和GoogleTestProject.vsz拷贝到以下目录:

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcprojects\GoogleTestProject。

 在New Project对话框中看到的效果就是:

VCWizards目录存放HTMLImagesScriptsTemplates等文件夹及相关文件,比如对于GoogleTestProject,我们可以把相关文件放置到以下目录:

	

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCWizards\GoogleTestProject。

对于编写好的向导,在部署集成到VS中时,需要修改.vsz文件中的ABSOLUTE_PATH字段,一般直接删除掉,如果有特殊需要可以使用RELATIVE_PATH,存放的位置要跟.vsz中设定的一致,否则向导引擎会因为无法找到对应模板文件报错。如果你需要部署向导到其他版本的VS,那么需要修改.vsz中的引擎版本,另外,如果是其他的语言版本,需要修改LangID(英文是1033、中文为2052),具体可以参考微软官方文档:将向导本地化为多种语言


五、常见问题


1.为什么修改了.ico.vsz.vsdir文件后没有生效(比如图标没变化)?

VS在第一次创建向导工程的时候会将上述三个文件直接拷贝到VS安装目录的vcprojects目录下,你在修改这些文件的时候,往往只是修改了工程目录下的文件,VS不会帮你同步这些更改到vcprojects目录,所以修改之后需要手动copy过去。

2.调试向导出现“没有对象”错误弹窗,或者工程建好后相应文件没有拷贝或者加入到新工程?

狗看到这个窗口是不是受到了万点暴击伤害?额~这个问题往往是你的default.js中没有实现必须要实现的回调函数造成,比如Common.js中的CreateProject函数需GetTargetName函数获取拷贝的目标文件名称,以及SetFileProperties函数来设置文件属性,遇到这种情况,在default.js中实现这些缺失的函数就可以了(参考我前文给出的框架代码)。

3.调试的时候断点无法命中?

编写调试期间,必须要保证你的.vsz文件描述的模板文件的目录指向向导工程目录下,也就是默认的ABSOLUTE_PATH,否则断点是不能命中的。当然,在后期部署的时候一定记得删掉ABSOLUTE_PATH或者使用RELATIVE_PATH

4.模板文件中的中文,编辑的时候好好的,新工程中渲染完毕就成了乱码?

很可能是因为你设置了错的LangID造成的,比如英文版VS创建的向导工程,默认的本地化语言使用的就是英语,那么在对应的模板文件中就不要使用中文。使用中文的话需要设置LangID为中文的编号2052,并且部署的时候拷贝到正确的文件夹下。

 最后留给大家个问题如果要完成向导自动化的部署,大家想的到有什么好的方法吗?



欢迎给测试窝投稿或参与内容翻译工作,请邮件至editors@testwo.com。也欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,并与我们的编辑和其他窝友交流。
141°|1419 人阅读|0 条评论

登录 后发表评论