技术开发 频道

强化Visual Studio单元测试

    名称和位置

    MSTEST.EXE最不成对的部分就是它的输出命名规范。如果你使用/RUNCONFIG选项来操作一个TESTRUNCONFIG文件,输出文件将使用在那个文件中规定的命名规范。如果你不使用/RUNCONFIG,或者设置为默认,所有的输出被写到.\TestResults\<user>_<machine> <timestamp>。我建议使用能够快速识别的名称。

    MSTEST.EXE提供了/RESULTSFILE选项,但是这将导致输出文件名称丢失时间戳。另外,如果指定到/RESULTSFILE的文件名称退出,MSTEST.EXE将会失败。我所希望的就是指定一个我所集中工作的细节的名称,但是不需要手动的添加时间戳。

    你可能会想可能的解决方法就是使用VSMDI测试源数据文件,这个文件你过去在测试管理器窗口中看到。事实上,MSTEST.EXE没有/TESTMETADATA选项来加载和运行测试。问题是你仅仅能指定一个VSMDI文件。

    一个可能的解决方案就是创建一个单独的VSMDI文件,这个文件在你的代码里面导入所有其它的VSMDI文件。那的确可以工作,但是它也呈现出另外一个维护任务来回忆每一次你添加新的测试到代码中。

    值得注意的是当运行VSMDI文件时你不能够告诉IDE或是MSTEST.EXE将输出文件放在什么位置。输出文件指向了VSMDI文件贮存的目录。建议在一个目录中保存测试,这个目录在版本控制里源代码之下,以致如果你共享项目,所有的测试代码将会跟随它

    由于VSMDI文件作为每一次测试的一部分,并且没有一种方式来集中输出,输出将围绕着你的源代码被分散。这并不是一个很大的处理,但是它意味着你必须手动的整理源树。在处理一些测试运行结果之后,我想要一种简单的方法来处理这个。

    一个更好的MSTEST.EXE

    基于此次论述,我明白了有四个特性我想添加到MSTEST.EXE。第一个是一种方法用来动态的发现所有的单元测试,然后就像小的smoke测试一样运行它们。第二个是一个简单的方法用来识别出相似的测试运行而不仅仅是读时间戳。第三个就是确保所有的测试输出定位到一个单一的位置。最后,我想要一种非常容易的方法来除去无关的测试运行而不管它们在源树中的什么位置。

    这些需求强烈要求MSBuild。Bugslayer.Build.Tests.DLL中的MSTestTask包装MSTEST.EXE所以你能够获得所有的控制。就像你看到的代码,你将注意到它是从ToolTask类获得的,并且是由Microsoft.Build.Utilities.DLL程序集产生的。当编写一个包装了一个命令行工具(因为它做了大部分的提高)build任务时,这个任务,ToolTask就是你想要使用的。

    对于一些工具,你所需要做的就是定义你唯一的属性,重载三个方法和一个属性。属性是ToolName,它返回了工具的可执行名称。GenerateFullPathToTool方法返回了完全的驱动,路径和文件名称到工具本身。为了验证这些参数,你需要重载ToolTask.ValidateParameters方法,如果一切正常的话,返回值为真。为了编译真实的命令行到工具中,重载ToolTask.GenerateCommandLineCommands然后使用CommandLineBuilder类或者是我对它做的简单的扩展ExtendedCommandLineBuilder。

    为所有可能的命令行参数运行MSTEST.EXE/?。当它指定输出文件名称的时候需要ResultsFile。你也需要设置TestMetaData参数或者TestContainer参数以此分别的显示出源数据文件或者测试容器。

    为所有可能的命令行参数运行MSTEST.EXE/?。当它指定输出文件名称的时候需要ResultsFile。你也需要设置TestMetaData参数或者TestContainer参数以此分别的显示出源数据文件或者测试容器。

    但是,我对于MSTestTask的长期计划就是扩展测试属性以允许通配符能够为测试名称的执行被通过。那将允许你容易的执行仅符合具体前缀的那些测试。借助在TestContainer属性中被通过的程序集,这工作将仅仅是一系列的反射,查找拥有TestClassAttribute的类库和一些符合规范表达的带有TestMethodAttribute的方法。

    MSTestTask其他的操作部分来自于RunTests.Targets文件,你可以在.\Build包含源代码的目录中找到这个文件。它包括了非常酷的ExecuteAllTests对象,这个对象在你指定的目录中开始,在整个结构中查找所有的单元测试,GenericTests,WebTests和OrderedTests,然后执行它们。你可以认为ExecuteAllTests对象对于单元测试是一个来说自动衰退测试。当你添加新的测试时,它将自动的执行它们。在代码下载中包含的RunTests.Targets代码非常明智的使用排除文件来获得我们希望的东西。为了查看一个使用中的RunTests.Targets例子,查看一下SmokeTest.proj,它为所有的代码显示出smoke测试。

    在.\Build目录中最后的TARGETS文件是MSTestCleanUp.Targets。就像它名称所暗示的那样,它的职责就是查找包含TestResults的所有目录作为一个路径然后删除它们。它是使用转换的一个很好的例子,就像MSBuild中的RemoveDuplicates任务一样。使用MSTestClean-Up.Targets,你就不用怕其他的文件毁坏你的源目录。

    掩饰,包装

    如果你不说,我将对Visual Studio 2005中新的单元测试工具非常兴奋。像ASP.NET和DataGrids这样的程序在此书中受到了所有的关注,但是当你努力按时获得程序时,测试工具将会带来很大的影响。我可以保证,你在使用测试工具上花费的时间越多,你的代码将会变的更好。

    Tip 73 你可以控制一个单元测试默认的编程语言和当一个新的单元测试被单元测试向导创建后哪些条目能被添加到里面。来到选项对话框,扩展测试工具节点,然后转到测试项目属性页面。在那,你将看到默认的测试项目类型combobox和每个语言类型的默认文件选择。如果你像我一样,在你创建了第二个单元测试后你将清除“About Test Projects”介绍文件。

    Tip 74 试图将一个程序集中的所有的单元测试保存到一个单一的测试程序集。那个一对一的映射来自于维护的观点。但是,当程序集增长时,测试数量将会变得非常大。我喜欢将前缀放到测试方法的名称上,因为这个它们测试的特性有关。这样可以很容易的分组。例如,在Bugslayer.Utility.Tests.DLL程序集中,关于GlobalMessageBox类的测试开始于”GNB_”

0
相关文章