24

你通常如何分离你的代码库和相关的单元测试?我认识一些为单元测试创​​建单独项目的人,我个人觉得这很混乱且难以维护。另一方面,如果您将代码及其测试混合在一个项目中,您最终会得到与您的单元测试框架(无论是 NUnit、MbUnit 还是其他任何东西)相关的二进制文件和您自己的二进制文件。

这对于调试来说很好,但是一旦我构建了发布版本,我真的不希望我的代码再引用单元测试框架

我发现的一种解决方案是将所有单元测试包含在#if DEBUG -- #endif 指令中:当没有代码引用单元测试程序集时,编译器足够聪明,可以忽略编译代码中的引用。

是否有任何其他(可能更舒适)的选择来实现类似的目标?

4

13 回答 13

42

我绝对主张将您的测试分离到一个单独的项目中。在我看来,这是唯一的出路。

是的,正如Gary所说,它还迫使您通过公共方法测试行为,而不是玩弄类的内部结构

于 2008-09-17T10:24:09.683 回答
21

正如其他人指出的那样,一个单独的测试项目(对于每个普通项目)是一个很好的方法。我通常镜像命名空间并为每个普通类创建一个测试类,并在名称后附加“test”。如果您拥有可以在另一个项目中自动生成测试类和方法的 Visual Studio Team System,则直接在 IDE 中支持这一点。

如果您想使用“内部”访问器测试类和方法,需要记住的一件事是将以下行添加到每个要测试的项目的 AssemblyInfo.cs 文件中:

[assembly: InternalsVisibleTo("UnitTestProjectName")]
于 2008-09-17T10:37:37.437 回答
10

v2 之后的 .Net 框架有一个有用的功能,您可以使用 InternalsVisibleTo 属性标记程序集,该属性允许其他人访问该程序集。
一种装配隧道功能。

于 2008-09-17T10:37:32.633 回答
9

在文件中使用编译器指令或创建单独项目的另一种替代方法是仅在项目中创建额外的 .cs 文件。

借助项目文件本身的一些魔力,您可以指定:

  1. nunit.framework DLL 仅在调试版本中引用,并且
  2. 您的测试文件仅包含在调试版本中

示例 .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>
于 2008-09-23T13:43:51.207 回答
3

我会推荐一个单独的单元测试项目(还有更多的集成测试、功能测试等项目)。我尝试在同一个项目中混合代码和测试,发现它比将它们分成单独的项目更难维护。

维护并行命名空间并为测试使用合理的命名约定(例如 MyClass 和 MyClassTest)将帮助您保持代码库的可维护性。

于 2008-09-17T10:32:20.257 回答
2

只要您的测试位于单独的项目中,测试就可以引用代码库,但代码库永远不必引用测试。我不得不问,维护两个项目有什么困惑?您可以将它们保留在相同的组织解决方案中。

当然,复杂的部分是当企业在解决方案中有 55 个项目并且其中 60% 是测试时。算自己幸运。

于 2008-09-17T10:45:40.537 回答
2

我将测试放在一个单独的项目中,但在同一个解决方案中。诚然,在大型解决方案中可能会有很多项目,但解决方案资源管理器在分离它们方面已经足够好了,如果你给所有的东西都提供合理的名称,我真的不认为这是一个问题。

于 2008-09-17T11:31:29.523 回答
2

需要考虑的一件事是 2005 年之前的 VisualStudio 版本不允许从其他项目引用 EXE 程序集项目。因此,如果您在 VS.NET 中处理遗留项目,您的选择将是:

  • 将单元测试放在同一个项目中,并使用条件编译将它们从发布版本中排除。
  • 将所有内容移至 dll 程序集,以便您的 exe 只是一个入口点。
  • 通过在文本编辑器中破解项目文件来绕过 IDE。

三个条件编译中最不容易出错。

于 2009-04-13T15:19:28.883 回答
1

我一直将我的单元测试保存在一个单独的项目中,以便它编译成它自己的程序集。

于 2008-09-17T10:24:38.280 回答
1

对于每个项目,都有一个相应的 .Test 项目,其中包含对它的测试。

例如,对于名为“Acme.BillingSystem.Utils”的程序集,会有一个名为“Acme.BillingSystem.Utils.Test”的测试程序集。

通过不发送该 dll 将其从产品的发货版本中排除。

于 2008-09-17T10:27:20.067 回答
1

如果#if(DEBUG)标签允许一个干净的“发布”版本,为什么你需要一个单独的项目进行测试。nunit LibarryA/B 示例(是的,我知道它是一个示例)就是这样做的。目前正在与场景搏斗。一直在使用一个单独的项目,但这似乎可能会提高一些生产力。仍然是hummin和hawin。

于 2009-07-08T15:12:05.953 回答
0

我绝对同意其他所有人的观点,即您应该将测试与生产代码分开。但是,如果您坚持不这样做,您应该定义一个称为 TEST 的条件编译常量,并用

#if TEST
#endif

首先要确保测试代码不会在生产场景中编译。完成后,您应该能够从生产部署中排除测试 dll,或者更好(但维护更高),为生产创建 NAnt 或 MSBuild,在没有对测试 dll 的引用的情况下进行编译。

于 2008-09-17T10:42:54.600 回答
0

我总是创建一个单独编译的 Acme.Stuff.Test 项目。

相反的论点是:您为什么要进行测试?为什么不交付测试?如果您与测试运行程序一起交付测试,您将获得与产品一起交付的某种程度的验收测试和自测。

我已经多次听到这个论点并考虑过,但我个人仍然将测试保留在一个单独的项目中。

于 2008-09-17T11:20:13.123 回答