我可以写两种方式之一的断言消息。说明成功:
assertEquals( "objects should be identical", expected, actual );
或说明被破坏的条件:
assertEquals( "objects aren't identical", expected, actual );
在JUnit中是否专门为此制定标准?如果没有,那么双方的论点是什么?
P.S。我在网上看到的文章都在没有说明的情况下展示了这两个文章,因此仅说“搜索Google”是无法解决的!
[UPDATE]
每个人都对我使用assertEquals
感到困扰,因此该消息可能毫无用处。但这当然只是因为我想简单地说明这个问题。
因此,想象一下它是:
assertTrue( ... big long multi-line expression ... );
消息有用处。
至少在assertEquals
中,我很少打扰消息。任何明智的测试跑步者都将说明您使用的是assertEquals
,这两个含义相等。您的任何一条消息都没有提供更多的信息。
我通常会发现单元测试失败是暂时性的,我会迅速找出问题所在并予以解决。 “找出问题所在”通常涉及足够的细节,以至于单个消息不会有太大的不同。考虑“通过收到一条消息节省的时间”与“花费在思考消息上的时间”:)
编辑:好的,我可能使用一条消息:当文本中有一个紧凑的描述,从对象的字符串表示形式中看不出来时。
例如:比较以毫秒为单位存储的日期时,“预计日期为12月1日。
不过,我不会担心您如何准确地表达它:只需确保从消息中清楚表明您的意思。 “应该是”或“不是”都可以-只是“ 12月1日”就不明显了。
根据junit API,该消息是“ AssertionError的标识消息”,因此它不是描述应该满足的条件的消息,而是描述如果不满足条件的问题的消息。因此,在您的示例中,“对象不相同”似乎更加一致。
[与许多其他人不同,我认为使用消息非常有用,原因有很多:
查看失败测试日志的人可能不是编写测试的人。可能需要花费一些时间来阅读代码并了解断言要解决的情况。有用的消息将节省时间。
即使是测试的开发人员正在查看自编写测试以来可能已经过了几天或几个月的日志,并且再次出现一条消息可以节省时间。
我的建议是在消息中写明预期的行为。例如:
assertEquals("The method should be invoked 3 times", 3, invocationCount);
我不认为这很重要-您已经知道发生了故障,因此,消息是否表明应该发生什么或不应该发生什么都没有关系。
消息的目标是在可能的情况下为您提供帮助,而不是获得某些完整性。
显然,在assertEquals的情况下,这没那么重要,但是在一般asserts的情况下,消息很重要。该消息应帮助您获得足够的上下文,以立即了解确切的失败原因。
但是,所需上下文的数量(以及消息中的详细信息)应取决于您如何获得报告。例如,如果您在Eclipse中获得它,则可以轻松地进行交互并查看发生了什么,因此消息的重要性降低了。但是,如果您将报告通过电子邮件发送给您(例如,从连续构建服务器发送给您),则您希望消息提供足够的信息,以便您甚至在转到相应的源代码之前就可以知道发生了什么。
[我想不考虑这个问题回答,是否有用的信息有用。
如果测试失败,则说明存在问题。我知道这个。我想知道为什么它坏了。这很容易发现,因为我只需要打开测试用例和SUT。就像乔恩(Jon)所说的那样,修复它非常容易(希望;-))。
但是消息呢?该消息对我来说是一个建议,可以采取什么措施将其变成绿色的测试用例。因此,如果消息文本中有建议,如何解决此问题或在何处搜索该问题,我将不胜感激。
另一个有趣的方面是正面表达的用法。使用正面文字消息值得考虑。在您的示例中,我将使用Objects should be identical
。但这是一个小原因。
我从两个角度看这个问题,
第一个也是最常见的角度,我们大多数人已经在这里进行了讨论:从看到日志并试图纠正错误的人的角度来看:我相信两条消息都提供相同的信息。
[第二种观点是正在阅读,维护/审查代码的人:正如我们自古以来一直在谈论代码的可读性和简单性一样。因此,它也同样重要。
我们被认为我的代码应该简单易懂,因此不需要明确的注释,我非常同意。
从这个角度来看:
这些消息使它们易于阅读和遍历代码,因为它们既具有文档编制功能,又具有错误报告的双重作用:
assertEquals( "objects should be identical", expected, actual );
assertTrue( "flag should have been set", flag );
assertNotNull( "object must not be null", object );
这些消息在谈论意外情况时不那么便于读者阅读:
assertEquals( "objects aren't identical", expected, actual );
assertTrue( "flag is not set", flag );
assertNotNull( "object is null", object );
根据规格,该消息用于描述错误发生的时间。当您在诸如Jenkins之类的CI环境中构建应用程序,并使用插件分析错误结果时,它非常有用。
http://junit.sourceforge.net/javadoc/org/junit/Assert.html#assertTrue(java.lang.String,%20boolean)
message-AssertionError的识别消息(可以,为空)
也投票给我(像乔恩一样),但我唯一一次使用过这样的消息(在断言等于时)是在使用值矩阵构建单个测试并且其中一个测试元素失败时:我使用指示哪个测试用例失败的消息。否则,该文本将完全多余。
从JUnit的javadocs:
断言两个对象相等。如果它们不是AssertionFailedError与给定的消息一起抛出。
根据API,该消息可以是您想要的任何消息。我认为您拥有的两个选项都是相同的,都是多余的。断言的成功或失败已经提供了您在消息中提供的所有信息。
对我来说,您应该什么都不做(有一个断言没有故意使用字符串),或者包含含义超出现有内容的消息。
所以我想这是对乔恩的回答的重申,但太冗长而无法发表评论。
我不会在您引用的情况下发出任何消息,除非我正在运行一个测试,在该测试中我有一个循环运行的相似测试值数组,并且我想确切指出哪个失败了。然后我添加一条消息告诉我哪个。
我同意提供信息是有帮助的,并且我总是提供信息。
对我来说,有用的是清楚地说明出了什么地方出了什么问题-通常涉及到“应该”或“不应该”这些词。
例如,“对象相等”是模棱两可的-是否表示对象相等,这就是测试失败的原因?还是说对象应该相等但不相等?但是,如果您说“对象应该相等”或“对象不应该相等”,那么断言失败的原因很明显。
我特别喜欢Spock测试框架如何鼓励那些读起来像故事的测试,并且同样在不同的框架下构造测试。我并不特别在意有意义的单个错误消息,我的目标是在打开测试后迅速将其包裹在整个测试中:
assertEquals("Cloned and persisted items", mockedTiCount, clonedTis.size());
assertTrue("Belong to new transaction", clonedTis.stream().allMatch(ti -> ti.getTransaction().getId().equals(cloned.getId())));
assertNotEquals("Which has a different ID", t.getId(), cloned.getId());
assertEquals("While the originals are left intact", mockedTiCount, transactionItemRepository.findByTransactionId(t.getId()).size());
选择很多小的测试而不是几个大的测试在这里也有帮助,结构整齐,希望可重用的测试设置代码也有帮助。
这些消息在测试失败时特别重要。当失败时,您不仅要知道对象应该相等,还想知道为什么它们应该相等。
所以代替
assertEquals( "objects should be identical", expected, actual );
使用
assertEquals( "Status code should be 403 (forbidden), because a user with role customer must not be allowed to access the admin console.", 403, statusCode );
并且是的,消息可以很长,只要它们可以帮助开发人员快速识别问题并以正确的方式解决它。