简体   繁体   English

C# - 从项目的发布版本中排除单元测试

[英]C# - Excluding unit tests from the release version of your project

How do you usually go about separating your codebase and associated unit tests ? 您通常如何分离代码库和相关的单元测试 I know people who create a separate project for unit tests, which I personally find confusing and difficult to maintain. 我知道有人为单元测试创​​建了一个单独的项目,我个人觉得这个项目令人困惑且难以维护。 On the other hand, if you mix up code and its tests in a single project, you end up with binaries related to your unit test framework (be it NUnit, MbUnit or whatever else) and your own binaries side by side. 另一方面,如果您将代码及其测试混合在一个项目中,最终会得到与您的单元测试框架(无论是NUnit,MbUnit还是其他任何内容)相关的二进制文件以及您自己的二进制文件。

This is fine for debugging, but once I build a release version , I really do not want my code to reference the unit testing framework any more. 这对于调试很好,但是一旦我构建了发布版本 ,我真的不希望我的代码再次引用单元测试框架

One solution I found is to enclose all your unit tests within #if DEBUG -- #endif directives: when no code references an unit testing assembly, the compiler is clever enough to omit the reference in the compiled code. 我找到的一个解决方案是将所有单元测试都包含在#if DEBUG - #endif指令中:当没有代码引用单元测试程序集时,编译器足够聪明,可以省略编译代码中的引用。

Are there any other (possibly more comfortable) options to achieve a similar goal? 是否还有其他(可能更舒适)的选择来实现类似的目标?

I definitely advocate separating your tests out to a separate project. 我绝对主张将你的测试分成一个单独的项目。 It's the only way to go in my opinion. 这是我认为的唯一方法。

Yes, as Gary says, it also forces you to test behavior through public methods rather than playing about with the innards of your classes 是的,正如加里所说,它也迫使你通过公共方法测试行为,而不是玩你班级的内脏

As the others point out, a seperate test project (for each normal project) is a good way to do it. 正如其他人所指出的那样,一个单独的测试项目(对于每个正常项目)是一个很好的方法。 I usually mirror the namespaces and create a test class for each normal class with 'test' appended to the name. 我通常镜像命名空间并为每个普通类创建一个测试类,并在名称后附加'test'。 This is supported directly in the IDE if you have Visual Studio Team System which can automatically generate test classes and methods in another project. 如果您拥有可以在另一个项目中自动生成测试类和方法的Visual Studio Team System,则可直接在IDE中支持此功能。

One thing to remember if you want to test classes and methods with the 'internal' accessor is to add the following line to the AssemblyInfo.cs file for each project to be tested: 如果要使用“内部”访问器测试类和方法,需要记住的一件事是将以下行添加到要测试的每个项目的AssemblyInfo.cs文件中:

[assembly: InternalsVisibleTo("UnitTestProjectName")]

The .Net framework after v2 has a useful feature where you can mark an assembly with the InternalsVisibleTo attribute that allows the assembly to be accessed by another. v2之后的.Net框架具有一个有用的功能,您可以使用InternalsVisibleTo属性标记程序集,该属性允许程序集被另一个访问。
A sort of assembly tunnelling feature. 一种装配隧道功能。

Yet another alternative to using compiler directives within a file or creating a separate project is merely to create additional .cs files in your project. 在文件中使用编译器指令或创建单独项目的另一种替代方法仅仅是在项目中创建其他.cs文件。

With some magic in the project file itself, you can dictate that: 通过项目文件本身的一些魔力,您可以指示:

  1. nunit.framework DLLs are only referenced in a debug build, and nunit.framework DLL仅在调试版本中引用,并且
  2. your test files are only included in debug builds 您的测试文件仅包含在调试版本中

Example .csproj excerpt: 示例.csproj摘录:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

   ...

   <Reference Include="nunit.framework" Condition=" '$(Configuration)'=='Debug' ">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\debug\nunit.framework.dll</HintPath>
   </Reference>

   ...

   <Compile Include="Test\ClassTest.cs" Condition=" '$(Configuration)'=='Debug' " />

   ...
</Project>

I would recommend a separate project for unit tests (and yet more projects for integration tests, functional tests etc.). 我会建议一个单独的项目进行单元测试(还有更多项目用于集成测试,功能测试等)。 I have tried mixing code and tests in the same project and found it much less maintainable than separating them into separate projects. 我尝试在同一个项目中混合代码和测试,发现它比将它们分成单独的项目更难维护。

Maintaining parallel namespaces and using a sensible naming convention for tests (eg. MyClass and MyClassTest) will help you keeping the codebase maintainable. 维护并行命名空间并对测试使用合理的命名约定(例如,MyClass和MyClassTest)将帮助您保持代码库的可维护性。

One thing yet to be considered is versions of VisualStudio prior to 2005 did not allow EXE assembly projects to be referenced from other projects. 有一点需要考虑的是,2005年之前的VisualStudio版本不允许从其他项目引用EXE组装项目。 So if you are working on a legacy project in VS.NET your options would be: 因此,如果您正在使用VS.NET中的旧项目,您的选项将是:

  • Put unit tests in the same project and use conditional compilation to exclude them from release builds. 将单元测试放在同一个项目中,并使用条件编译将它们从发布版本中排除。
  • Move everything to dll assemblies so your exe is just an entry point. 将所有内容移动到dll程序集,这样你的exe只是一个入口点。
  • Circumvent the IDE by hacking the project file in a text editor. 通过在文本编辑器中破解项目文件来绕过IDE。

Of the three conditional compilation is the least error prone. 三个条件编译中最不容易出错。

For each project there is a corresponding .Test project that contains tests on it. 对于每个项目,都有一个相应的.Test项目,其中包含测试。

Eg for the assembly called, say "Acme.BillingSystem.Utils", there would be a test assembly called "Acme.BillingSystem.Utils.Test". 例如,对于被称为“Acme.BillingSystem.Utils”的程序集,将会有一个名为“Acme.BillingSystem.Utils.Test”的测试程序集。

Exclude it from the shipping version of your product by not shipping that dll. 通过不发送该dll将其从产品的发货版本中排除。

As long as your tests are in a seperate project, the tests can reference the codebase, but the codebase never has to reference the tests. 只要您的测试处于单独的项目中,测试就可以引用代码库,但代码库从不必参考测试。 I have to ask, what's confusing about maintaining two projects? 我不得不问,维护两个项目有什么困惑? You can keep them in the same solution for organization. 您可以将它们保存在组织的相同解决方案中。

The complicated part, of course, is when the business has 55 projects in the solution and 60% of them are tests. 当然,复杂的部分是当企业在解决方案中有55个项目时,其中60%是测试。 Count yourself lucky. 算你自己幸运。

I put the tests in a separate project but in the same solution. 我把测试放在一个单独的项目中但是在同一个解决方案中。 Granted, in big solutions there might be a lot of projects but the solution explorer is good enough on separating them and if you give everything reasonable names I don't really think it's an issue. 当然,在大型解决方案中可能会有很多项目,但解决方案资源管理器在分离它们方面已经足够好了,如果你给出了所有合理的名称,我并不认为这是一个问题。

If the #if(DEBUG) tag allows for a clean "release" version, why would you need a separate project for tests. 如果#if(DEBUG)标签允许一个干净的“发布”版本,为什么你需要一个单独的项目进行测试。 The nunit LibarryA/B example (yeah, I know its a example) does this. nunit LibarryA / B的例子(是的,我知道它的一个例子)这样做。 Currently wrestling with the scenario. 目前正在与场景搏斗。 Had been using a separate project, but this seems to possibly allow for some productivity improvements. 曾经使用过一个单独的项目,但这似乎可以提高生产力。 Still hummin and hawin. 仍然是hummin和hawin。

我总是把我的单元测试放在一个单独的项目中,所以它编译成它自己的程序集。

I definitely agree with everyone else that you should separate the tests from your production code. 我绝对同意其他人的意见,你应该将测试与生产代码分开。 If you insist on not, however, you should define a conditional comiplation constant called TEST, and wrap all of your unit test classes with a 但是,如果你坚持不这样做,你应该定义一个名为TEST的条件编写常量,并用一个包装所有单元测试类

#if TEST
#endif

first to ensure that the test code does not compile in a production scenario. 首先要确保测试代码不在生产场景中编译。 Once that is done, you should either be able to exclude the test dlls from your production deployment, or even better (but higher maintenance), create an NAnt or MSBuild for production that compiles without the references to the test dlls. 完成后,您应该能够从生产部署中排除测试dll,或者甚至更好(但更高的维护),为生产创建一个NAnt或MSBuild,在没有引用测试dll的情况下进行编译。

I always create a separate Acme.Stuff.Test project that is compiled separately. 我总是创建一个单独编译的单独的Acme.Stuff.Test项目。

The converse argument is: Why do you want to take the tests out? 相反的论点是:你为什么要考试? Why not deliver the test? 为什么不提供测试? If you deliver the tests along with a test runner you have some level of acceptance test and self test delivered with the product. 如果您将测试与测试运行器一起交付,则您需要对产品进行一定程度的验收测试和自检。

I've heard this argument a few times and thought about it but I personally still keep tests in a separate project. 我已经听过几次这个论点并考虑过它,但我个人仍然在一个单独的项目中进行测试。

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

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