我已经开始研究整个单元测试/测试驱动开发的想法,我越想它,它似乎就越扮演与静态类型检查类似的角色。这两种技术都可以对程序中的某些类型的错误提供编译时、快速响应的检查。但是,如果我错了,请纠正我,但似乎完全覆盖的单元测试套件将测试静态类型检查将测试的所有内容,然后是一些。或者换句话说,静态类型检查只是“证明”程序正确性的一部分,而单元测试将让您“证明”尽可能多的内容(在一定程度上)。

那么,如果您也使用单元测试,是否有理由使用具有静态类型检查的语言?有人问了一个有点类似的问题 这里, ,但我想了解更多细节。静态类型检查相对于单元测试有哪些具体优势(如果有的话)?我想到了一些问题,例如编译器优化和智能感知,但是这些问题还有其他解决方案吗?还有其他我没有想到的优点/缺点吗?

有帮助吗?

解决方案

我认为自动单元测试对动态类型语言来说是重要,但这并不意味着它会替换您应用的上下文中的静态类型检查。事实上,一些使用动态类型的人实际上可能正在使用它,因为他们想要不断进行类型安全检查的麻烦。

动态类型语言提供的优于静态类型语言的优势远不止于测试,类型安全仅仅是一个方面。动态和静态类型语言的编程风格和设计差异也有很大差异。

此外,写得过于强烈执行类型安全的单元测试意味着软件不应该动态输入,或者应用的设计应该用静态类型语言编写,而不是动态类型。

其他提示

软件质量有一个不可改变的事实。

  

如果无法编译,则无法发货

在此规则中,静态类型语言将赢得动态类型语言。

好的,是的,这条规则不是一成不变的。 Web应用程序无需编译即可发布(我已部署了许多未编译的测试Web应用程序)。但基本上是真的是

  

越早发现错误,就越便宜了

静态类型语言可以防止在软件开发周期中最早的某个时刻发生真正的错误。动态语言不会。单元测试,如果你是一个超级人类级别的彻底可以取代静态类型的语言。

然而为什么要打扰?有很多非常聪明的人在那里以编译器的形式为您编写完整的错误检查系统。如果您担心错误很快就会使用静态类型语言。

请不要将这篇文章视为动态语言的抨击。我每天都使用动态语言并喜欢它们。它们具有令人难以置信的表现力和灵活性,并允许令人难以置信的迷人程序。但是在早期错误报告的情况下,它们确实会失去静态类型语言。

对于任何合理大小的项目,您只能通过单元测试来解释所有情况。

所以我的回答是<!>“;没有<!>”,即使你设法解释所有情况,你也因此首先打败了使用动态语言的整个目的。

如果您想编写类型安全的程序,最好使用类型安全的语言。

拥有100%的代码覆盖率并不意味着您已经完全测试了您的应用程序。请考虑以下代码:

if (qty > 3)
{
    applyShippingDiscount();
}
else
{
    chargeFullAmountForShipping();
}

如果我输入qty = 1和qty = 4的值,我可以获得100%的代码覆盖率。

现在假设我的业务条件是<!>“; ...对于3件或更多件物品的订单,我要对运费进行折扣.. <!>”;然后我需要编写有关边界的测试。所以我会设计qty为2,3和4的测试。我仍然有100%的覆盖率,但更重要的是我在逻辑中发现了一个错误。

这就是我仅关注代码覆盖的问题。我认为最多你会遇到开发人员根据业务规则创建一些初始测试的情况。然后,为了提高覆盖率,他们在设计新的测试用例时引用它们的代码。

清单类型(我想你的意思是)是一种规范形式,单元测试要弱得多,因为它只提供示例。重要的区别在于,规范声明了在任何情况下都必须保持的内容,而测试仅涵盖示例。您永远无法确定您的测试是否涵盖了所有边界条件。

人们也往往会忘记声明类型作为文档的价值。例如,如果 Java 方法返回 List<String>, ,然后我立即知道我得到了什么,无需阅读文档、测试用例甚至方法代码本身。类似地对于参数:如果声明了类型,那么我就知道该方法需要什么。

声明局部变量类型的价值要低得多,因为在编写良好的代码中,变量存在的范围应该很小。不过,您仍然可以使用静态类型:您无需声明类型,而是让编译器推断它。像这样的语言 斯卡拉 甚至 C# 让您能够做到这一点。

某些类型的测试更接近规范,例如 快速检查 或者它是 Scala 变体 Scala检查 根据规范生成测试,尝试猜测重要的边界。

我会用不同的方式说出来 - 如果你没有静态类型的语言,如果你计划做任何事情,那么更好有非常彻底的单元测试<!> <!>真实QUOT;用那个代码。

那就是说,静态打字(或者更确切地说,显式打字)比单元测试有一些显着的好处,这些测试让我更喜欢它。它创建了更易理解的API,并允许快速查看<!> quot; skeleton <!>;应用程序(即入口指向每个模块或代码段)的方式使用动态类型语言要困难得多。

总结一下:在我看来,通过坚实,彻底的单元测试,动态类型语言和静态类型语言之间的选择主要是品味之一。有些人喜欢一个;其他人更喜欢另一个。使用正确的工具完成工作。但这并不意味着它们是相同的 - 静态类型的语言总是以某种方式具有优势,而动态类型的语言总是以某种不同的方式具有优势。单元测试对于最大限度地减少动态类型语言的缺点有很大帮助,但它们并没有完全消除它们。

没有

但这不是最重要的问题,最重要的问题是:它不能重要吗?

考虑静态类型检查的目的:避免一类代码缺陷(错误)。但是,必须在所有代码缺陷的较大域的上下文中对其进行权衡。最重要的不是沿着狭窄的条子进行比较,而是对代码质量的深度和广度进行比较,编写正确代码的简易性等等。如果您能够提出一种开发风格/流程,使您的团队能够提高质量没有静态类型检查更有效地编码,那么它是值得的。即使在您的测试中存在静态类型检查会捕获的漏洞的情况下也是如此。

我想如果你非常彻底就可以。但为什么要这么麻烦?如果语言已经检查以确保静态类型是正确的,那么测试它们就没有意义了(因为你可以免费获得它)。

此外,如果您使用IDE的静态类型语言,IDE甚至可以在编译测试之前为您提供错误和警告。我不确定是否有任何自动单元测试应用程序可以执行相同的操作。

鉴于动态的,后期绑定语言的所有好处,我认为这是单元测试提供的价值之一。你仍然需要仔细和有意识地编码,但这是任何类型的编码恕我直言的第一要求。能够编写清晰简单的测试有助于证明您的设计和实施的清晰度和简单性。它还为稍后查看代码的人提供了有用的线索。但我不认为我会依靠它来检测不匹配的类型。但实际上我并没有发现类型检查确实能够捕获许多真正的错误。如果你在一开始就有一个清晰简单的编码风格,那么这不是我在实际代码中发现的一种错误。

对于javascript,我希望jsLint能找到几乎所有的类型检查问题。主要是通过建议替代编码风格来减少曝光。

类型检查有助于在系统中的组件之间强制执行合同。单元测试(顾名思义)验证组件的内部逻辑。

对于单个代码单元,我认为单元测试确实可以使静态类型检查变得不必要。但是在复杂的系统中,自动化测试无法验证系统的不同组件可能会以多种方式进行交互。为此,使用 interfaces (在某种意义上,它们是组件之间的一种<!>“contract <!>”)成为减少潜在错误的有用工具。接口需要编译时类型检查。

我非常喜欢用动态语言编程,所以我当然不会抨击动态类型。这只是我最近遇到的一个问题。不幸的是,我没有任何使用动态语言来处理大型复杂系统的经验,所以我有兴趣听听其他人是否真实,或仅仅是理论问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top