【问题标题】:Keep your Source Close and your Unit Tests Closer保持你的源代码和你的单元测试更接近
【发布时间】:2023-04-03 13:11:01
【问题描述】:

当我第一次开始使用单元测试时,我遇到了两个问题。首先是能够测试私有方法和字段,其次是在快速开发发生时使单元测试保持最新。因此,我采用以下方法进行单元测试。

#if UNITTEST
using NUnit.Framework;
#endif

public class MyBlackMagic
{
   private int DoMagic()
   {
      return 1;
   }

   #if UNITTEST

   [TestFixture]
   public class MyBlackMagicUnitTest
   {
        [TestFixtureSetUp]
        public void Init()
        {
             log4net.Config.BasicConfigurator.Configure();
        }

        [Test]
        public void DoMagicTest()
        {
             Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
             Assert.IsTrue(DoMagic() == 1, "You are not a real magician!");
         }
     }

     #endif
 }

我发现这种方法克服了我的两个问题,并且只需轻按预编译器开关即可确保所有单元测试都能编译。

我现在的问题是我正在转移到一个新项目,其中讨论的是使用单独的程序集来进行单元测试。在我深入并开始阐述如上所示的内部类方法的优点之前,我想知道是否有人认为它有任何缺点?

编辑:

只是围绕一些提到的弱点补充几点:

  • 单元测试代码永远不会影响生产代码,因为 UNITTEST 预编译器标志已关闭,
  • 单元测试代码不会降低主代码的可读性,因为它位于每个类的底部并包装在 Visual Studio 区域指令中,
  • 我发现内部单元测试类意味着主类实际上更简单,因为没有为了测试而必须公开的额外方法或属性。在某些情况下,您迟早要在单元测试中测试某个类的某些内部状态...

【问题讨论】:

    标签: c# unit-testing nunit


    【解决方案1】:

    我觉得这种方法很丑陋,因为它用测试方法混淆了你的真实逻辑,使你的源代码更难阅读。

    除此之外,您还拥有对项目本身中的 NUnit 程序集的依赖项(引用)。虽然在没有 unit_test 条件定义的情况下编译时不需要依赖,但这很丑陋且没有必要。

    如果你想跟上你的单元测试,我建议你先写测试,然后实现真正的代码。

    编写单元测试不仅仅是测试;这也是关于设计代码。

    通过首先编写测试,您将考虑 API/类的接口,或者您希望如何使用这些类。

    【讨论】:

    • 我同意第一部分,但我不明白“先编写测试”如何解决问题。 “易于测试”只是设计公共界面的利益相关者之一。虽然它在很大程度上与良好的设计相关,但它却是一个糟糕的“总体目标”。
    • 首先编写测试并不是要拥有一个易于测试的设计;这是关于有一个良好的整体/可用的类设计。因此,您进行的测试是额外的好处。反正你写的软件毕竟是要测试的,何不多花点时间写个测试..
    【解决方案2】:

    您不应该单独测试私有方法,因为它们(应该!)从公共方法或可能的构造函数中使用 - 因此公共方法依赖于私有方法才能成功完成分配。

    如果私有方法不起作用,这些公共方法/构造函数将(应该!)失败。所以你的方法实际上是编写单元测试的不好方法。

    并迭代以前的答案 - 在编写方法之前编写单元测试。

    【讨论】:

      【解决方案3】:

      如果您不能始终保持所有测试成功(因为开发截止日期),那么我认为您没有非常认真地进行单元测试,您应该在进行估算时考虑到测试的维护。

      【讨论】:

        【解决方案4】:

        我发现将我的单元测试保存在他们自己的程序集中效果很好,并且在使用它时没有遇到任何问题。

        但是,如果您发现自己需要测试某个班级的私有成员,那可能意味着您的班级正在做很多事情。您最好将这些私有成员提取到一个新类中。然后,您可以直接通过其公共方法测试该新类。

        【讨论】:

          【解决方案5】:

          请问您如何在将UNITTEST 设置为 false 的任何构建上运行单元测试?

          我是一个蹩脚、懒惰的 TDD 实施者。我没有写任何接近足够测试的地方,我也不会太频繁地运行它们。但即使我测试我的发布版本。

          【讨论】:

          • “请告诉我,您如何在任何将 UNITTEST 设置为 false 的构建上运行单元测试?”你不……这不是重点吗?
          • 您不知道将 UNITTEST 设置为 false 的构建是否通过了您的单元测试。这让我觉得是个问题。
          【解决方案6】:

          我认为这不是单元测试的目的。如果您已经快速开发代码并且您的单元测试落后,那么它们当然会失败,但这不应该导致您使用黑魔法,而是编写单元测试。如果您不喜欢这种方式,那么您根本不应该使用单元测试。

          【讨论】:

            【解决方案7】:

            将测试代码保留在自己的单独程序集中的基本原理是因为测试代码不应该被用户“使用”。单元测试仅用于验证代码是否执行指定的操作。通常的做法是将测试代码放在自己的程序集中,这样生产代码就不会依赖于测试代码和单元测试框架。

            从这个代码示例中,我不清楚您要测试什么。似乎您正在尝试测试未与环境完全隔离的东西。当 xUnit 测试运行器可以为您记录测试结果时,为什么还需要记录器?

            内部类很难测试,因为您需要一个内部类正在实现的公共接口(或抽象类),并且您需要与创建它的类一起测试它。更明确的单元测试应该检查一个特定类的行为,如果一个内部类以某种方式返回,那么你需要检查它是否以正确的方式返回。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-10-05
              • 1970-01-01
              • 2013-06-18
              • 1970-01-01
              • 2010-10-04
              • 1970-01-01
              • 2011-11-24
              • 1970-01-01
              相关资源
              最近更新 更多