这是一个非常有趣的主题,这里也有很多非常有教育意义的答案!下面是我从他们那里学到的: 1.直觉/反直觉可以被认为是主观的,所以不管它最初被定义的顺序是什么,也许是50% of us would not be happy。 1.就我个人而言,我更希望它被设计为assertEqual(actual, expected),因为考虑到assert和if之间的概念相似性,我希望它遵循if actual == expect的规范,例如if a == 1。 (PS:确实,有不同的意见提示以“相反的顺序”编写if语句,即if(1==a) {...},以防止意外地丢失一个=。但这种风格远远不是规范,即使在C/C++世界中也是如此。如果你碰巧在编写Python代码,你一开始就不会受到这种讨厌的错别字的影响,因为if a = 1在Python中无效。) 1.执行assertEqual(expect, actual)的实际理由是,你的语言中的unittest库很可能已经按照这个顺序生成了可读的错误消息。例如,在Python中,当你执行assertEqual(expected_dictionary, actual_dictionary)时,unittest will display missing keys in actual with prefix - , and extra keys with prefix +,就像你执行git diff old_branch new_branch一样。 不管直观与否,这是坚持assertEqual(expected, actual)顺序的唯一最有说服力的理由。如果你碰巧不喜欢它,你最好还是接受它,因为"practicality beats purity"。 1.最后,如果你需要一种方法来帮助你记住顺序,this answer将assertEqual(expected_result, actual_calculation)与赋值语句的顺序result = calculate(...)进行比较。这是一种记忆事实行为的好方法,但恕我直言,这不是一种更直观的顺序推理。 所以给你。快乐assertEqual(expect, actual)!
9条答案
按热度按时间wrrgggsh1#
answer来自Kent Beck,JUnit的共同创建者(可能是这个约定的起源,因为他早期的SUnit doesn't appear to have included
assertEquals
):把一堆Assert等号排成一行。先有预期会让他们读得更好。
在我最初的答案中,我说我不明白这一点。下面是我在测试中经常看到的:
我认为首先使用 actual 值会读起来更好。这将更多的重复样板放在一起,对齐我们正在测试的值的方法调用:
(And还有其他原因使我更喜欢这个顺序,但对于这个问题的目的,即“为什么"是另一种方式,肯特的推理似乎是答案。)
然而,Bob Stein在下面有一条评论(很像这条),它建议了“expected first”的几个优点。主要的想法是,期望值通常较短--通常是文字或变量/字段,而不是复杂的方法调用。结果是:
谢谢你,鲍勃!
4c8rllxm2#
因为作者有50%的几率符合你的直觉。
由于其他过载
而解释,也就是你所知道的一部分,与预期的,也就是你所知道的,相对于实际的,你在写代码的时候并不知道。
igsr9ssn3#
assertEqual()
的另一个目的是为人类读者演示代码。一个简单的函数调用在左侧显示返回值,在右侧显示调用。
按照该约定,函数的自测演示如下所示:
顺序为(预期,实际)。
下面是sum()函数的一个演示,左边是一个字面的expected返回值,右边是一个计算actual返回值的函数调用:
类似地,下面是一个表达式的演示,它也是按(预期的,实际的)顺序自然排列的:
另一个原因是风格上的。如果你喜欢把东西排列起来,expected参数放在左边更好,因为它往往更短:
我怀疑这解决了@ChrisPovirk提出的关于肯特Beck所说的“期望第一使他们读得更好”的谜团。
感谢Andrew Weimholt和Ganesh Parameswaran提供这些公式。
5uzkadbs4#
我同意一致性是第一位的共识,但是如果你在评估这个问题,比较字典的行为可能是一个有用的数据点。
当我在diff上看到一个“+”时,我会把它读成“被测试的过程添加了这个”。
注意:我使用了按字母顺序排列的键,并增加了字典的长度,这样只有中间的一个键会发生变化,以使示例更加清晰。其他场景显示了更多模糊的差异。同样值得注意的是,assertEqual在〉=2.7和〉=3.1中使用了assertDictEqual
exl.py
输出量:
nwnhqdif5#
这是一个非常有趣的主题,这里也有很多非常有教育意义的答案!下面是我从他们那里学到的:
1.直觉/反直觉可以被认为是主观的,所以不管它最初被定义的顺序是什么,也许是50% of us would not be happy。
1.就我个人而言,我更希望它被设计为
assertEqual(actual, expected)
,因为考虑到assert
和if
之间的概念相似性,我希望它遵循if actual == expect
的规范,例如if a == 1
。(PS:确实,有不同的意见提示以“相反的顺序”编写if语句,即
if(1==a) {...}
,以防止意外地丢失一个=
。但这种风格远远不是规范,即使在C/C++世界中也是如此。如果你碰巧在编写Python代码,你一开始就不会受到这种讨厌的错别字的影响,因为if a = 1
在Python中无效。)1.执行
assertEqual(expect, actual)
的实际理由是,你的语言中的unittest库很可能已经按照这个顺序生成了可读的错误消息。例如,在Python中,当你执行assertEqual(expected_dictionary, actual_dictionary)
时,unittest will display missing keys in actual with prefix-
, and extra keys with prefix+
,就像你执行git diff old_branch new_branch
一样。不管直观与否,这是坚持
assertEqual(expected, actual)
顺序的唯一最有说服力的理由。如果你碰巧不喜欢它,你最好还是接受它,因为"practicality beats purity"。1.最后,如果你需要一种方法来帮助你记住顺序,this answer将
assertEqual(expected_result, actual_calculation)
与赋值语句的顺序result = calculate(...)
进行比较。这是一种记忆事实行为的好方法,但恕我直言,这不是一种更直观的顺序推理。所以给你。快乐
assertEqual(expect, actual)
!ibps3vxo6#
xUnit测试惯例是预期的/实际的。所以,对于许多人来说,这是自然的顺序,因为这是他们学到的。
有趣的是,与xUnit框架的惯例不同,qunit使用的是actual/expected。至少在javascript中,你可以创建一个新的函数来封装旧的函数,并将原来的变量赋给它:
h5qlskok7#
assertEqual
的文档将第一个参数命名为first
,将第二个参数命名为second
:assertEqual(first, second, msg=None)
测试
first
和second
是否相等。如果两个值不相等,则测试失败。然而,如果你看一下文档中的大多数例子,你会发现他们把收到的价值放在第一位,而期望值放在第二位(与你的问题贴所宣称的相反):
所以我会说约定是
assertEqual(got, expected)
,而不是相反!不管怎样,你的测试仍然有效。
swvgeqrz8#
我有点惊讶还没有看到这个答案,因为它一直似乎是最有可能的解释给我。
假设你没有
assertEquals
,而只有assert
,你会怎么写测试呢?你可以把它写为:但是在很多情况下,它们不是同一个对象,只是等价的对象,所以(这可能与语言有关),你不能可靠地使用
==
运算符来表达你的意图,所以你把它换成:在一段时间内一切都很好。但是随后你引入了一个bug,测试失败了,因为结果(实际)变成了***null***。但是测试并没有像你期望的那样失败--相反,你甚至根本不能调用
actual.equals
,因为你甚至没有一个对象来调用方法!你的测试代码因为一个异常而崩溃,因为测试本身是脆弱的。许多使用OO语言的人已经习惯了这一点,他们养成了编写所有基于方法的条件语句的习惯,比如
if ("foo".equals(myString))
,在myString
为空的情况下,这仍然是安全的(尽管相反的情况就不安全了)。因此,写Assert的 * 最佳习惯 * 是:
...如果实际值错误,甚至为空,则会失败。
一旦你在这种情况下花了几年时间,并且你决定用
assertEquals
方法编写一个单元测试框架,那么你只会感觉到一种自然的参数顺序:)6xfqseft9#
我听到的解释是它来自TDD。
在测试驱动开发中,您从测试开始,然后编写代码。
通过编写期望值来启动Assert,然后调用应该生成它的代码,是这种心态的一个迷你版本。
当然,这可能只是人们讲的一个故事,不知道是不是有意识的原因。