代码之家  ›  专栏  ›  技术社区  ›  Aaron

条件编译是单元测试的有效模拟/存根策略吗?

  •  4
  • Aaron  · 技术社区  · 16 年前

    在最近一个关于存根的问题中,许多答案都建议使用C接口或实现存根的委托,但是 one answer 建议使用条件编译,在生产代码中保留静态绑定。这个答案是在阅读时修改的-2,所以至少有2个人真的认为这是一个 错误的 回答。可能是因为错误使用了调试,或者使用了固定值而不是更广泛的验证。但我不禁想:

    条件编译的使用是否是实现单元测试存根的不适当的技术?有时?总是?

    谢谢。

    编辑添加: 我想增加一个例子作为一个实验:

    class Foo {
        public Foo() { .. }
        private DateTime Now { 
          get {
    #if UNITTEST_Foo
            return Stub_DateTime.Now;
    #else
            return DateTime.Now;
    #endif
          }
        }
        // .. rest of Foo members
    }
    

    比较

    interface IDateTimeStrategy { 
        DateTime Now { get; }
    }
    class ProductionDateTimeStrategy : IDateTimeStrategy {
      public DateTime Now { get { return DateTime.Now; } }
    }
    class Foo {
        public Foo() : Foo(new ProductionDateTimeStrategy()) {}
        public Foo(IDateTimeStrategy s) { datetimeStrategy = s; .. }
        private IDateTime_Strategy datetimeStrategy;
        private DateTime Now { get { return datetimeStrategy.Now; } }
    }
    

    它允许通过C接口终止对“datetime.now”的传出依赖。但是,我们现在添加了一个动态调度调用,其中静态调用就足够了,对象甚至在生产版本中也更大,并且我们为foo的构造函数添加了一个新的失败路径(分配可能会失败)。

    我是不是什么都不担心?感谢您迄今为止的反馈!

    6 回复  |  直到 16 年前
        1
  •  3
  •   Gishu    16 年前

    尝试将生产代码与测试代码分开。维护不同的文件夹层次结构..不同的解决方案/项目。

    除非 …你在传统C++代码的世界里。有什么事吗……如果条件块帮助您获得一些可测试的代码,您会看到一个好处。一定要做到。但不要让它比初始状态更混乱。清楚地注释和划分条件块。小心操作。它是在测试工具下获取遗留代码的有效技术。

        2
  •  2
  •   plyawn    16 年前

    我认为这会降低审查代码的人的清晰度。您不必记住在特定代码周围有一个条件标记来理解上下文。

        3
  •  1
  •   Aaron Jensen    16 年前

    不,这太糟糕了。它将测试泄漏到您的生产代码中(即使它已关闭)

    坏坏。

        4
  •  1
  •   Amy B    16 年前

    测试代码应该是明显的,并且不能与被测试代码在同一块中相互混合。

    这和你不应该写的原因差不多

    if (globals.isTest)
    
        5
  •  1
  •   Aaron Jensen    16 年前

    我想到了另一个可怕的原因:

    很多时候,您模拟/存根一些东西,您希望它的方法根据您测试的内容返回不同的结果。这要么排除了这一点,要么让它变得很尴尬。

        6
  •  0
  •   Bradley Harris    16 年前

    当您重构大型代码库中的可测试性时,它可能是一个有用的工具。我可以看到您如何使用这些技术来实现较小的更改并避免“大爆炸”重构。然而,我担心过于依赖这种技术,并试图确保这种技巧不会在代码库中使用太长时间,否则会使应用程序代码变得非常复杂和难以执行。