Why do so many assertEquals()
or similar function take the expected value as first parameter and the actual one as second ?
This seems counter-intuitive to me, so is there a particular reason for this unusual order ?
相关问题
- how to define constructor for Python's new Nam
- streaming md5sum of contents of a large remote tar
- How to get the background from multiple images by
- Evil ctypes hack in python
- Correctly parse PDF paragraphs with Python
This is a very intesting topic, and lots of very educational answers here too! Here is what I learn from them:
Intuitive/counter-intuitive can be considered as subjective, so no matter which order it was originally defined, perhaps 50% of us would not be happy.
Personally I would have preferred it were designed as
assertEqual(actual, expected)
, because, given the conceptual similarity betweenassert
andif
, I would wish it follows the norm ofif actual == expect
, for example,if a == 1
.(PS: It is true that there are different opinions which prompts to write if statement in the "reverse order", i.e.
if(1==a) {...}
, in order to guard you from accidentally missing one=
. But that style was far from the norm, even in the C/C++ world. And if you happen to be writing Python code, you are not vulnerable to that nasty typo in the first place, becauseif a = 1
is not valid in Python.)The practical convincing reason to do
assertEqual(expect, actual)
, is that the unittest library in your language likely already follows that order to generate readable error message. For example, in Python, when you doassertEqual(expected_dictionary, actual_dictionary)
, unittest will display missing keys in actual with prefix-
, and extra keys with prefix+
, just like when you do agit diff old_branch new_branch
.Intuitive or not, this is the single most convincing reason to stick with the
assertEqual(expected, actual)
order. If you happen to not like it, you better still accept it, because "practicality beats purity".Lastly, if you need a way to help you remember the order, this answer compares
assertEqual(expected_result, actual_calculation)
to the assignment statement orderresult = calculate(...)
. It can be a good way to MEMORIZE the de-facto behavior, but IMHO it is not the undebatable reasoning of that order is more intuitive.So here you go. Happy
assertEqual(expect, actual)
!The answer from Kent Beck, creator of SUnit and JUnit (where possibly this convention originates), is:
However, this is so opposite to my own experience that I have to wonder if I'm misunderstanding it. Here's what I often see in tests:
I would think this would read better with the actual value first. That puts more of the repetitive boilerplate together, aligning the method calls whose values we're testing:
(And there are other reasons that I prefer this order, but for the purpose of this question about why it's the other way, Kent's reasoning appears to be the answer, even if I haven't understood it.)
I agree with the consensus that consistency is #1, but the behavior of comparing dictionaries may be a helpful datapoint if you're evaluating this question.
When I see a "+" on a diff, I read this as "the procedure being tested added this." Again, personal preferences apply.
Note: I used alphabetized keys and made the dictionary longer so that only a middle key would change for clarity of the example. Other scenarios display more obfuscated diffs. Also noteworthy, assertEqual uses assertDictEqual in >=2.7 and >=3.1
exl.py
Output:
Because the authors had a 50% chance of matching your intuition.
Because of the other overload
And the explanation, which is part of what you know, goes with the expected, which is what you know, as opposed to the actual, which you don't know at the time you write the code.
The explanation I heard is that it comes from TDD.
In Test Driven Development, you start with the test, and then write the code.
Starting assertions by writing the expectation, and then call the code that should produce it, is a mini version of that mindset.
Of course, this may just be a story people tell. Don't know that it was a conscious reason.
The xUnit testing convention is expected/actual. So, for many that is the natural order since that's what they learnt.
Interestingly in a break from convention for an xUnit framework qunit goes for actual/expected. At least with javascript you can just create a new function that encapsulates the old one and assign it the original variable: