tl;博士
此页面上的大多数其他答案都推动了格言“断言通常不用于生产代码”。虽然在诸如文字处理器或电子表格之类的生产力应用程序中是正确的,但在 Java 如此常用的自定义业务应用程序中,断言 -生产中的测试非常有用,而且很常见。
就像编程世界中的许多格言一样,在一种情况下开始正确的东西会被误解,然后在其他情况下被误用。
生产力应用
“断言通常不用于生产代码”这句格言虽然很常见,但却是不正确的。
形式化的断言测试起源于诸如Microsoft Word之类的文字处理器或Microsoft Excel之类的电子表格之类的应用程序。这些应用程序可能会在用户每次击键时调用一系列断言测试断言。这种极端的重复严重影响了性能。因此,只有在有限分发中的此类产品的 beta 版本才启用断言。因此格言。
商业应用
相比之下,在面向业务的数据输入、数据库或其他数据处理应用程序中,在生产环境中使用断言测试非常有用。对性能的微不足道的影响使它非常实用 - 并且很常见。
测试业务规则
在生产运行时验证您的业务规则是完全合理的,应该受到鼓励。例如:
- 如果发票必须始终具有一个或多个行项目,则编写一个断言测试,而不是发票行项目的计数大于零。
- 如果产品名称必须至少包含 3 个字符或更多字符,请编写一个测试字符串长度的断言。
- 在计算现金分类帐的余额时,您知道结果永远不会是负数,因此请检查是否存在负数,表明数据或代码存在缺陷。
此类测试对生产性能没有显着影响。
运行时条件
如果您的应用程序期望某些条件在您的应用程序在生产中运行时始终为真,请将这些期望作为断言测试写入您的代码中。
如果您期望这些条件有时会合理地失败,那么不要编写断言测试。也许抛出某些异常。然后在可能的情况下尝试恢复。
健全性检查
在生产运行时进行健全性检查也是完全合理的,应该受到鼓励。当一些奇怪的事情发生时,测试一些人们无法想象是不真实的任意条件已经在无数情况下拯救了我的培根。
例如,在某个库中测试将镍 (0.05) 四舍五入导致镍 (0.05) 有助于我成为第一批发现 Apple 在其Rosetta库中发布的浮点技术缺陷的人之一。PowerPC 到 Intel 的过渡。这样的缺陷传播到公众似乎是不可能的。但令人惊讶的是,该漏洞并未引起原始供应商 Transitive 和 Apple 以及对 Apple 测试版进行测试的早期开发人员的注意。
(顺便说一句,我应该提一下......永远不要使用浮点数来赚钱,使用BigDecimal
。)
框架的选择
assert
您可能需要考虑使用另一个断言框架,而不是使用内置工具。您有多种选择,包括:
或者自己动手。制作一个小类以在您的项目中使用。像这样的东西。
package work.basil.example;
public class Assertions {
static public void assertTrue ( Boolean booleanExpression , CharSequence message ) throws java.lang.AssertionError {
if ( booleanExpression ) {
// No code needed here.
} else { // If booleanExpression is false rather than expected true, throw assertion error.
// FIXME: Add logging.
throw new java.lang.AssertionError( message.toString() );
}
}
}
示例用法:
Assertions.assertTrue(
localTime.isBefore( LocalTime.NOON ) ,
"The time-of-day is too late, after noon: " + localTime + ". Message # 816a2a26-2b95-45fa-9b0a-5d10884d819d."
) ;
你的问题
他们来得比较晚(Java 1.4),那时很多人已经建立了他们的 Java 编程风格/习惯
是的,这是完全正确的。许多人对 Sun/JCP 为断言测试开发的 API 感到失望。与现有图书馆相比,它的设计乏善可陈。如此多的人忽略了新的 API,并坚持使用已知的工具(第 3 方工具或滚动您自己的迷你库)。
默认情况下,它们在运行时关闭,WHY OH WHY??
在最早的几年里,Java 因性能速度差而受到诟病。具有讽刺意味的是,Java 迅速发展成为性能最佳的平台之一。但糟糕的说唱就像一股臭味。因此,Sun 对任何可能以任何可衡量的方式影响性能的事情都非常警惕。因此,从这个角度来看,将禁用断言测试设为默认值是有意义的。
另一个默认禁用的原因可能与 Sun 在添加新的断言工具时劫持了单词assert
. 这不是以前保留的关键字,并且需要对 Java 语言进行的少数更改之一。该方法名称assert
已被许多库和许多开发人员在他们自己的代码中使用。有关此历史转变的一些讨论,请阅读此旧文档Programming With Assertions。