简体   繁体   English

我可以使用NUnit和NCrunch通过预处理器指令测试多个构建配置吗?

[英]Can I Use NUnit & NCrunch to Test Multiple Build Configurations with Preprocessor Directives?

I am writing a wrapper library for the API to some software that has multiple versions of the API, and lots of shared calls between multiple platforms that are developed concurrently but separately. 我正在为具有多个API版本的某些软件编写API的包装库,并在多个同时开发但分别开发的平台之间进行大量共享调用。 Over time they have even been merging the platforms to use the same code base, just under different namespaces & *.exe builds. 随着时间的流逝,他们甚至将平台合并为使用相同的代码库,只是在不同的命名空间和* .exe构建下。

I'm doing this by writing one single code base, and then using preprocessor directives and conditional compilation symbols through build configurations to selectively use certain code for the builds. 我这样做是通过编写一个单一的代码库,然后通过构建配置使用预处理程序指令和条件编译符号来有选择地将某些代码用于构建。 About 90% of the code can literally be reused between versions and platforms, so this is helpful. 实际上,大约90%的代码可以在版本和平台之间重用,因此这很有用。 All works fine on the project-under-test end. 在被测项目结束时一切正常。

However, I am having issues using NUnit & NCrunch to unit test this project. 但是,使用NUnit和NCrunch对这个项目进行单元测试时遇到问题。 I created identical build configurations to load the correct constants and create the correct build folders for the Integration Test project. 我创建了相同的构建配置,以加载正确的常量并为Integration Test项目创建正确的构建文件夹。 However, I am noticing two strange problems: 但是,我注意到两个奇怪的问题:

  1. NUnit seems to be ignoring preprocessor directives in the Integration Test project. NUnit似乎忽略了Integration Test项目中的预处理程序指令。 For example, in the following example, the first line of code is always hit (BUILD_Foov16=true) regardless of configuration (eg BUILD_Bar_2015=true), even though in Visual Studio it appears that the desired line set (corresponding to the current configuration variables) is the only one active: 例如,在下面的示例中,无论配置如何(例如BUILD_Bar_2015 = true),始终会命中第一行代码(BUILD_Foov16 = true),即使在Visual Studio中看起来像是所需的行集(与当前配置变量相对应) )是唯一一个活动的:

     [TestFixture] public class FooBarIncApplicationTests { #if BUILD_Foov16 public const string path = @"C:\\Program Files (x86)\\FooBarInc\\FooV16\\Foo.exe"; #elif BUILD_Foov17 public const string path = @"C:\\Program Files (x86)\\FooBarInc\\FooV17\\Foo.exe"; #elif BUILD_Bar_2013 public const string path = @"C:\\Program Files (x86)\\FooBarInc\\Bar 2013\\Bar.exe"; #elif BUILD_Bar_2015 public const string path = @"C:\\Program Files (x86)\\FooBarInc\\Bar 2015\\Bar.exe"; #endif [Test] public void FooBarIncApplication_Initialize_New_Instance_Defaults() { using (FooBarIncApplication app = new FooBarIncApplication(path)) { ... } } } 
  2. Additionally, it seems that when I run a test through NCrunch, it is only using the *.dll corresponding to the build created by the first configuration listed (eg it is always testing the *.dll compiled for Foo.exe v16. 此外,似乎当我通过NCrunch运行测试时,它仅使用与列出的第一个配置所创建的版本相对应的* .dll(例如,它始终在测试针对Foo.exe v16编译的* .dll。

It seems to me like these two issues are related. 在我看来,这两个问题是相关的。 I am wondering if NUnit and/or NCrunch cannot handle such a setup, or if there is a particular way I should be dealing with this unique setup? 我想知道NUnit和/或NCrunch是否无法处理这样的设置,或者是否有一种特殊的方式应对这种独特的设置?

My bigger issue is #2, which is that NCrunch seems to be running NUnit only on the *.dll built from the first configuration, which makes it impossible to test any of the other configurations. 我更大的问题是#2,这是NCrunch似乎仅在从第一种配置构建的* .dll上运行NUnit,这使得无法测试任何其他配置。 Perhaps this is a problem with project dependencies? 也许这是项目依赖的问题? (The path in the example above is to the program that I am interacting with via the API, but not my *.dll projects.) (上面示例中的路径是我通过API与之交互的程序,而不是我的* .dll项目。)

OK, I found out what the problem was. 好的,我发现了问题所在。 This is worth knowing if you are ever testing NCrunch for multiple DLL build configurations! 如果您是否曾经针对多个DLL构建配置测试NCrunch,这是值得知道的!

When NCrunch runs, the *.dll generated and the code coverage ascertained (and stepped through) is NOT affected by the current configuration specified in Visual Studio. 当NCrunch运行时,生成的* .dll和确定的代码覆盖率(并逐步执行)不受Visual Studio中指定的当前配置的影响。 It is always determined by the project default configuration at the time that Visual Studio loads the project. 它总是由Visual Studio加载项目时的项目默认配置确定。 This means that in order to change configurations for testing, you need to modify the *.csproj file. 这意味着,为了更改测试配置,您需要修改* .csproj文件。

For example, I have configuration definitions for Foov16 and Foov17 shown below. 例如,我有以下所示的Foov16和Foov17的配置定义。 In order to set the project to Foov17 in such a way that NCrunch will work, the configuration for Foov17 must be referenced in the default configuration (the first element): 为了以NCrunch可以使用的方式将项目设置为Foov17,必须在默认配置(第一个元素)中引用Foov17的配置:

<PropertyGroup>
   <Configuration Condition=" '$(Configuration)' == '' ">Debug-Foov17</Configuration>
   <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
   <ProjectGuid>{...}</ProjectGuid>
   <OutputType>Library</OutputType>
   <AppDesignerFolder>Properties</AppDesignerFolder>
   <RootNamespace>FooBarInc.API</RootNamespace>
   <AssemblyName>FooBarInc.API</AssemblyName>
   <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
   <FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Foov16|AnyCPU'">
   <DebugSymbols>true</DebugSymbols>
   <OutputPath>bin\AnyCPU\Debug-Foov16\</OutputPath>
   <DefineConstants>TRACE;DEBUG;BUILD_Foov16</DefineConstants>
   <DebugType>full</DebugType>
   <PlatformTarget>AnyCPU</PlatformTarget>
   <ErrorReport>prompt</ErrorReport>
   <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
   <DocumentationFile>bin\AnyCPU\Debug-Foov16\FooBarInc.API.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Foov17|AnyCPU'">
   <DebugSymbols>true</DebugSymbols>
   <OutputPath>bin\AnyCPU\Debug-Foov17\</OutputPath>
   <DefineConstants>TRACE;DEBUG;BUILD_Foov17</DefineConstants>
   <DebugType>full</DebugType>
   <PlatformTarget>AnyCPU</PlatformTarget>
   <ErrorReport>prompt</ErrorReport
   <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
   <DocumentationFile>bin\AnyCPU\Debug-Foov17\FooBarInc.API.XML</DocumentationFile>
</PropertyGroup>

Not sure if that helps you. 不确定是否对您有帮助。 If I understood you correctly you want to inject different exe paths in a test case and let the test case run for every exe path. 如果我理解正确,则希望在测试用例中插入不同的exe路径,并让测试用例针对每个exe路径运行。 You can try to use NUnits TestCase attribute for this. 您可以尝试为此使用NUnits TestCase属性。 Example from NUnit website: NUnit网站上的示例:

   [TestCase(12,3,4)]
   [TestCase(12,2,6)]
   [TestCase(12,4,3)]
   public void DivideTest(int n, int d, int q)
   {
     Assert.AreEqual( q, n / d );
   }

Based on that you may rewrite your test to: 基于此,您可以将测试重写为:

[TestCase(@"C:\Program Files (x86)\FooBarInc\FooV16\Foo.exe")]
[TestCase(@"C:\Program Files (x86)\FooBarInc\FooV17\Foo.exe")]
public void FooBarIncApplication_Initialize_New_Instance_Defaults(string path)
{
    using (FooBarIncApplicatio app = new FooBarIncApplicatio(path))
    {
    ...
    }
 }

Base on that the testcase will run with version 16 and version 17 of your exe. 基于此,测试用例将与您的exe的版本16和版本17一起运行。 Additional benefit: You don't have to switch your VS configurations to run all tests. 额外的好处:您不必切换VS配置即可运行所有测试。

If you still want to use conditional test case execution you can either use the Category or the System.Diagnostics.Conditional attribute. 如果仍然要使用条件测试用例执行,则可以使用CategorySystem.Diagnostics.Conditional属性。 See this stackoverflow link for additional information. 有关其他信息,请参见此stackoverflow链接

Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM