Parameters 如何有效地对动态语言的参数进行单元测试?

Parameters 如何有效地对动态语言的参数进行单元测试?,parameters,dynamic-languages,Parameters,Dynamic Languages,在动态语言中如何处理参数类型与Java中的静态语言(我的透视图被告知或变形,这是您喜欢的)相比,我从未理解过的一件事上触动了我的神经 给定一个在动态语言中接受参数条的方法foo,在编译时不会强制执行该类型的条。上面链接的答案(以及我通常看到的答案)是,您需要在动态语言中正确地进行单元测试 但在某个时刻,该单元之外的某些东西会调用该方法。假设这是一个很重的对象,它将在使用它的类的任何单元测试中被模拟。现在有许多类调用此方法,需要更改类型。为了保持简单,它过去需要一个数字,但现在需要一个字母数字,并

在动态语言中如何处理参数类型与Java中的静态语言(我的透视图被告知或变形,这是您喜欢的)相比,我从未理解过的一件事上触动了我的神经

给定一个在动态语言中接受参数条的方法foo,在编译时不会强制执行该类型的条。上面链接的答案(以及我通常看到的答案)是,您需要在动态语言中正确地进行单元测试

但在某个时刻,该单元之外的某些东西会调用该方法。假设这是一个很重的对象,它将在使用它的类的任何单元测试中被模拟。现在有许多类调用此方法,需要更改类型。为了保持简单,它过去需要一个数字,但现在需要一个字母数字,并且您需要使用一个专门用于字符串的方法,而不是用于具有新要求的数字对象

您如何更改它并知道调用代码将被修复?当然,如果您只是更改它,单元测试将失败,但由于您需要故意更改它,您表面上会修复单元测试。您如何知道如何修复呼叫代码?我的意思不仅仅是你在概念上知道多少,我的意思是你如何知道你已经找到了所有的呼叫者,并且可以说它已经改变了


似乎只有非常全面的集成测试才能为您提供这种保证。我遗漏了什么吗?

我需要15个字符才能发布,但答案是4个字符:grep。

这似乎更像是一个重构问题,而不是一个单元测试问题


通过确保特定函数中需要的所有属性和方法都存在并返回预期结果,可以有效地对参数进行单元测试。重要的不是接口的类型。

简单的回答就是“更多的单元测试”

唯一重要的是,新类型还具有所需的方法。因此,如果
ClassA
有Method1(),它接受一个参数
obj
,并调用
obj#M1()
obj#M2()
,那么obj的唯一约束就是它响应这些消息。如果将实现更改为调用以前不存在的方法
Foo()
,则执行类a的测试将失败


接下来,如果
ClassB
调用
A#Method1()
作为其功能的一部分,那么如果类B通过了一个obj,则其测试将失败,而obj确实具有所需的方法。如果没有达到B所需的行为,它的测试应该失败,这应该直接导致B中所需的更改。

我认为您已经给出了一个极好的具体示例,说明了静态类型的优点之一。动态键入要求您自己查找所有这些呼叫位置。但这其实并不难——它只是代码中的文本搜索。这是一个折衷方案:编译器可以交叉引用您的代码并确保所有内容都匹配,而不是在代码中使用分散注意力的类型标记

  • 防御性编码。使更改在新方法中向后兼容。根据参数的类型进行分派;这很容易

  • 使用编辑器或IDE的“谁调用”函数


  • 动态语言开发人员需要复制静态类型的优点,也就是说,工具可以自动发现这些错误。在大多数情况下,这涉及类型推断工具。推理本身相当困难(我正在为PHP写博士论文),但使用这些工具并不十分困难

    有以下错误查找工具:

    • 红宝石:
    • Python:
    • Javascript:,但我看不到它可以下载
    对于PHP,只需非常少量的工作就可以做到这一点


    总的来说,当你没有静态类型时,你需要一个工具来获得好处。

    谢谢,但这就是为什么我明确给出了一个重对象的例子——比如说一个可以访问数据库的对象,你必须模拟它才能进行合理的单元测试。好的。。既然我们在动态语言中没有强类型接口,那么我们如何确保真实对象支持相同的消息集呢?我想说的是,有一些验收测试使用真正的合作者,而不是在每秒执行的测试套件中。。我认为强耦合类不是一个好的解决方案。即使它使测试变得更容易,它也会使代码变得更混乱。我想这就是答案。我想说的是,类型标签可能是一个负担,只是分散注意力。我花了大量时间严格地“修复”代码以满足类型系统,更不用说因为它而复制代码了。不要用Java来判断静态类型。它的类型系统强大到足以让你烦恼,但却不足以帮你解决很多问题。您至少应该检查OCaml.+1。静态和动态都是关于权衡的。你得到一些东西,你必须放下一些东西。简单重构就是其中之一。然而,我不认为答案是4个字符长。这几天简直太糟糕了。:)