【问题标题】:Splitting test classes into partial classes?将测试类拆分为部分类?
【发布时间】:2016-05-18 14:14:27
【问题描述】:

我正在寻找一种在 .NET 项目中组织单元测试的好方法。现在,每个应用程序类都有一个TestClass,每种方法都有多个测试。虽然我使用TestCategory 来根据它测试的应用程序类方法对每个TestMethod 进行分类,但发现我的测试方法变得很笨拙。

我正在考虑将我的测试类拆分为部分类 - 每个应用程序类方法一个部分类。这意味着我可以在每个方法的一个专用文件中拥有多个 TestMethod,而无需在大文件中寻找它们。

这种方法有什么缺陷吗?在 .NET 和 Visual Studio 中处理大型测试类是否有更好的方法?

编辑:我正在使用 IoC(我们在测试之外使用 Castle.Windsor 进行 DI)并且我们使用 Moq 来模拟功能。使用TestInitialize 初始化测试。

【问题讨论】:

  • 您可以为每个方法创建一个测试类。例如,您有一个类 C1,其方法为 M1M2。创建 2 个测试类,C1_M1_TestC1_M2_Test
  • 考虑将您的测试类拆分为多个较小的类,而不是拆分您的测试。
  • @Carra No...一个方法可能有多个测试。如果一个类有 3 个方法,每个方法有 6 个测试……那就是一个测试类中有 18 个测试。更改应用程序类并不能真正解决问题 - 它正在解决等式错误一侧的增长规模。
  • @Carra 老实说......我意识到,正如你所做的那样,可伸缩性不是根本问题。事实上,我们必须担心函数中的控制流。一个函数可能会根据其输入抛出三种不同的异常。它可能返回一个空对象或一个非空对象。我讨厌驳回您的评论,因为您实际上并没有错……如果没有联合类型、不可变对象和引用透明方法,很难将其中一些问题分开。这是可行的,但可能不值得我和我的团队付出代价。

标签: c# .net visual-studio


【解决方案1】:

看看我的回答C# ASP.NET MVC Controller unit test。 它的要点是:

  • 一个静态类,它包含给定的所有测试 被测系统。
  • 为每个测试场景提供一个测试类 从基类继承的运行

此设置的另一个好处是它为您提供了一个很好的测试树,如果您使用 resharper 单元测试会话能够轻松找到您的测试。

至于第一个答案,您不应该在测试中使用 DI 框架。所有外部依赖项都应该被模拟/伪造,以便您只测试被测系统。

对于使用部分类。见Are C#'s partial classes bad design?

我同意 Carra 的观点,仅使用部分类来拆分长类被认为是糟糕的设计。如果你的班级这么大,可能需要拆分。

【讨论】:

  • 嗯。我可能会考虑继承模式,但我不使用 Resharper。我不确定在我的情况下是否需要静态类。我们正在使用模拟,但我们没有在测试本身中使用 DI(我们在应用程序中)。我想我要解决的真正问题是缺乏嵌套的测试规范——我觉得每个方法的类范式是一个非常糟糕的解决方案。
  • 基本上......我意识到,我正在寻找类似于Mocha 中的describe 功能的东西 - 一种在逻辑上构建我的测试的方法,而无需跳过箍来这样做.
  • 静态类不用于resharper,它是对特定类的所有测试场景进行逻辑分组。每个方法可能有超过 1 个类,具体取决于该方法中的任何分支逻辑。您也可以将多个测试归为一类。请注意,在我的示例中,我如何在第一个实例中进行多个测试,因为它们不会改变测试过程。然后我将具体场景分解为自己的测试。
  • 我最终使用了in this article 描述的技术,这与您的建议类似,除了没有不必要的静态包装类。我使用基类作为包装类。因此,我在一个地方对所有测试进行了初始化,我有“描述”功能(很容易在代码中找到测试),我仍然可以镜像我的目标项目(每个应用程序文件一个测试文件),我在测试中获得免费分组explorer,我没有遇到任何缺点。总的来说,很棒!
【解决方案2】:

我会让您的测试简单明了。分离你的测试可能是有益的,但你在哪里初始化你的测试代码?您是否正在使用控制反转来完成其他测试应该已经完成​​的工作?如果是这样,那么您可能需要查看 [TestInitialize] 并开始组织您的依赖项。

这就是集中化 TestInit 的意思

[TestClass]
public class UnitTestWebsiteBuilderPattern
{
    private IHtmlInputService _htmlInputService;
    private IHtmlControlService _htmlControlService;
    private IHtmlMenuControlService _htmlMenuControlService;
    private IHtmlConditionalInputService _htmlConditionalInputService;
    private IHtmlPanelService _htmlPanelService;
    private IHelpIconService _helpIconService;
    private IHtmlModalService _htmlModalService;

    [TestInitialize]
    public void Init()
    {
        _helpIconService = new HtmlHelpIconService();

        _htmlInputService = new HtmlInputService(_helpIconService);
        _htmlPanelService = new HtmlPanelService(_htmlInputService);

        _htmlModalService = new HtmlModalService(_htmlPanelService);
        _htmlControlService = new HtmlControlService(_htmlPanelService);

        _htmlMenuControlService = new HtmlMenuControlService();
        _htmlConditionalInputService = new HtmlConditionalInputService();

    }

【讨论】:

  • 我已经这样做了,使用起订量。这里的多个类的问题是我最终会在任何地方重复这段代码(除非我从与应用程序类匹配的基测试类继承,或其他东西)。
  • 您可以使用 di 集中您的 app_start 以进行单元测试 private static void RegisterServices(IKernel kernel)
  • 因为您使用的是温莎城堡,您可以最小起订量预期结果并断言您的预期是正确的。至于用于测试的部分类以某种方式使测试更有趣和更简单,请重新设计。 codeproject.com/Articles/5772/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 2020-09-12
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 2010-10-14
  • 2021-01-28
相关资源
最近更新 更多