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

用与代码不同的语言编写单元测试有什么好处?

  •  10
  • ctford  · 技术社区  · 15 年前

    单元测试的要求与生产代码不同。例如,单元测试可能不必像生产代码那样执行。

    也许有时候用更适合编写单元测试的语言编写单元测试是有意义的?我想到的具体例子是用C语言编写一个应用程序,但是使用IronRuby或Ironpython编写测试。

    如我所见,使用Ironpython和IronRuby比使用C代码作为测试语言有几个优势:

    • 在动态类型语言中模拟可以更简单。
    • Ironpython的详细类型注释在单元测试中不需要。
    • 通过在解释器上键入命令,在不重新编译的情况下进行测试调用

    在测试和生产代码中使用两种不同语言的权衡是什么?

    10 回复  |  直到 13 年前
        1
  •  11
  •   Stefan Steinegger    15 年前

    我想到的缺点是:

    • 根据语言的不同,你需要另一种语言 开发环境 (项目的附加依赖关系、安装开发机器的附加工作、附加许可证、附加培训…)
    • 重构 有时是由IDE支持的,但大多数情况下可能不支持这种其他语言。所以您必须手动重构它们。
    • 单元测试也可以用作 编程示例 . 测试显示了测试类的用途。如果测试是用另一种语言编写的,那么这就不能很好地工作。
        2
  •  7
  •   Jon Skeet    15 年前

    一个明显的潜在问题是令人困惑的调试体验。我个人没有尝试过在.NET中跨语言进行调试-如果您从Ironpython进入C代码,会发生什么?

    另一个问题是,任何想要在代码基础上开发的人都必须知道这两种语言。

        3
  •  3
  •   Ray Vernagus    15 年前

    我是铁杆语言的狂热爱好者,但在使用它们测试静态编译的代码时有很大的缺点。用ruby/python测试ruby/python非常有效,也就是说,您可以以任何方式伪造对象。但是使用Ruby/python测试C会导致比预期更复杂的问题。

    考虑一个场景,您正在编写一个ASP MVC项目,在该项目中,您希望假冒出向控制器发出请求的浏览器类型。在c中,您可以这样模拟它(使用moq):

    var fakeRequest = new Moq.Mock<System.Web.HttpRequestBase>();
    fakeRequest.Setup(request => request.Browser.Type).Returns("Fake");
    

    在IronRuby中,它看起来像这样:

    class FakeBrowser < HttpBrowserCapabilitiesBase
      def type
        "Fake"
      end
    end
    
    class FakeRequest < HttpRequestBase
      def browser
        FakeBrowser.new
      end
    end
    

    需要伪造的上下文越深,就越复杂。在C中,模拟框架自动为您进行子类型划分,但不幸的是,在动态语言中,您将有很多工作要做。像pymock或mocha这样的模拟库不适用于这样的测试,因为测试中的代码有很强的类型依赖性,并且由ruby/python框架生成的伪对象将不符合这些依赖性。我希望看到随着IronRuby和Ironpython的成熟,情况会有所改善,但是现在测试C的情况并不那么好。

    如果我认为这是错误的,我愿意接受纠正。=)

        4
  •  2
  •   Paddy    15 年前

    我认为它的主要缺点是可维护性。如果您使用C编码,那么您的开发团队和新员工都能胜任这一语言。你需要一个多功能开发团队。

    我认为也值得注意的是,你可能不希望人们用一种可能不是他们最强的语言来编写他们的测试。您的测试代码需要是健壮的。

    您还需要在编写代码/测试时在语法之间切换-这有点麻烦。

        5
  •  2
  •   Murph    15 年前

    我认为这是一个很好的问题,也是一个值得考虑的想法,特别是在像Visual Studio/.NET这样的环境中,它很容易得到支持。

    正如您所建议的,好处是您可以选择使用一种语言/工具来创建比您用来创建代码更适合创建测试的测试,并且仅出于这个原因,这是值得考虑的。

    正如建议的那样,不利的一面是您的开发人员——那些创建测试的开发人员(我们必须记住不要将单元测试与测试驱动的设计混淆起来),可能应该能够流利地使用多种语言(我建议这样做的能力对一个好的开发人员来说相当重要,但我有偏见!)-更重要的是,您可能需要担心这两种语言之间的结构差异(不过,如果您谈论的是应该涵盖的.NET语言,请再说一遍)。

    如果您将“单元”测试扩展到所有级别的测试,那么它会变得更加有趣,在这些级别上,特定语言的特定功能可能会在构建测试用例方面带来优势。

    最终的问题是优势是否大于劣势…这可能有点具体。

        6
  •  1
  •   Yuriy Faktorovich    15 年前

    最大的折衷是,如果有人正在考虑使用单元测试来确定某个操作是如何执行的,用另一种语言编写它会使它更难使用。此外,您还必须使您的C代码符合CLS。

        7
  •  1
  •   Alex B    15 年前

    在构建API或库时,我经常以文档的形式提供单元测试,说明如何最好地使用API或库。大多数时候,我构建一个C库,我将交付给一个将编写C代码以使用库的客户机。

    出于文档方面的考虑,至少我的一些测试将始终用目标语言编写。

        8
  •  1
  •   tvanfosson    15 年前

    最大的缺点是,您也在单元测试中测试编译器依赖性。从某种意义上说,这也使它们成为集成测试。如果您希望您的代码可以从多种语言中使用,这可能会使它们更可取,但是如果您的代码只能在生产中与开发它所使用的语言一起使用,那么它会增加一个您可能不需要的复杂性级别。

    我可以看到的一个优点是它进一步将正在开发的代码与测试本身隔离开来。通过将编写测试的行为与正在开发的实际代码分离,它迫使您真正考虑应该如何编写代码来通过测试,而不是简单地将代码的初始开发移动到测试本身。

        9
  •  1
  •   Mark Seemann    15 年前

    我同意其他的答案,即有缺点,但我很惊讶,这么少的人谈论优点。

    • 跨语言的TDD是学习新语言的一个很好的方法:用您熟悉的语言编写测试,并用您正在学习的语言实现。在您学习的过程中,您将发现编写代码的更好方法,但重构很容易,因为您有一个测试套件。
    • 必须掌握多种语言才能使你(和你的团队)保持敏锐。
    • 您可以更好地验证您的API是否可以跨语言进行互操作。
        10
  •  0
  •   Stephen Swensen    13 年前

    经验1

    在过去的一年里,我从事的一个项目有两个主要部分:

    1. Grails Web应用程序
    2. 一个JAVA Swing应用程序

    我们使用Groovy编写了Java单元测试,结果很好。使用groovy进行单元测试所花费的时间要少得多,而且可以伪造静态方法等等。尽管有几个地方由于groovy的动态类型,我们遇到了意想不到的结果,但总的来说,这是一个积极的体验。

    经验2

    我最近工作的另一个项目是C ASP.NET MVC 3 Web应用程序,在该应用程序中,我用F编写了所有单元测试。我选择了C作为Web应用程序,因为我觉得它在MVC 3上工作得更好。我选择f作为单元测试,因为它是我最喜欢的语言。我遇到的唯一问题是对像 null VS option .

    结论

    当我们有两种语言针对同一个运行时(分别是CLR和JRE上的Cy/F/Z和Java/Groovy),其中一个用于生产代码,一个用于单元测试,至少对于兼容性没有太多的担心。然后,我认为这真的是一个问题,您和您的团队在这两种语言中是否感到足够舒适(我想您可能也会考虑未来的维护人员)。事实上,我认为你在单元测试中不得不使用不同语言的时候,是指单元测试语言实际上是你舒适的语言,或者是你对生产语言的选择。

    我承认这种自由主义态度有一些例外。如果您正在设计一个由语言X使用的库,那么用语言X编写单元测试可能是一个明智的想法(至少有些是这样)。但是对于应用程序代码,我从未发现用与生产代码相同的语言编写单元测试特别有利。