Unit testing: why is the expected argument always first in equality tests?

Unit Testing

Unit Testing Problem Overview


Why is it that every unit testing framework (that I know of) requires the expected value in equality tests to always be the first argument:

Assert.AreEqual(42, Util.GetAnswerToLifeTheUniverseAndEverything());

assertEquals(42, Util.GetAnswerToLifeTheUniverseAndEverything());

etc.

I'm quite used to it now, but every coder I try to teach unit testing makes the mistake of reversing the arguments, which I understand perfectly. Google didn't help, maybe one of the hard-core unit-testers here knows the answer?

Unit Testing Solutions


Solution 1 - Unit Testing

It seems that most early frameworks used expected before actual (for some unknown reason though, dice roll perhaps?). Yet with programming languages development, and increased fluency of the code, that order got reversed. Most fluent interfaces usually try to mimic natural language and unit testing frameworks are no different.

In the assertion, we want to assure that some object matches some conditions. This is the natural language form, as if you were to explain your test code you'd probably say

> "In this test, I make sure that computed value is equal to 5"

instead of

> "In this test, I make sure that 5 is equal to computed value".

Difference may not be huge, but let's push it further. Consider this:

Assert.That(Roses, Are(Red));

Sounds about right. Now:

Assert.That(Red, Are(Roses));

Hm..? You probably wouldn't be too surprised if somebody told you that roses are red. Other way around, red are roses, raises suspicious questions. Yoda, anybody?

That doesn't sound natural at all

Yoda's making an important point - reversed order forces you to think.

It gets even more unnatural when your assertions are more complex:

Assert.That(Forest, Has.MoreThan(15, Trees));

How would you reverse that one? More than 15 trees are being had by forest?

This claim (fluency as a driving factor for modification) is somehow reflected in the change that NUnit has gone through - originally (Assert.AreEqual) it used expected before actual (old style). Fluent extensions (or to use NUnit's terminology, constraint based - Assert.That) reversed that order.

Solution 2 - Unit Testing

I think it is just a convention now and as you said it is adopted by "every unit testing framework (I know of)". If you are using a framework it would be annoying to switch to another framework that uses the opposite convention. So (if you are writing a new unit testing framework for example) it would be preferable for you as well to follow the existing convention. I believe this comes from the way some developers prefer to write their equality tests:

if (4 == myVar)

To avoid any unwanted assignment, by mistake, writing one "=" instead of "==". In this case the compiler will catch this error and you will avoid a lot of troubles trying to fix a weird runtime bug.

Solution 3 - Unit Testing

Nobody knows and it is the source of never ending confusions. However not all frameworks follow this pattern (to a greater confusion):

  1. FEST-Assert uses normal order:

     assertThat(Util.GetAnswerToLifeTheUniverseAndEverything()).isEqualTo(42);
    
  2. Hamcrest:

     assertThat(Util.GetAnswerToLifeTheUniverseAndEverything(), equalTo(42))
    
  3. ScalaTest doesn't really make a distinction:

     Util.GetAnswerToLifeTheUniverseAndEverything() should equal (42)
    

Solution 4 - Unit Testing

I don't know but I've been part of several animated discussions about the order of arguments to equality tests in general.

There are a lot of people who think

if (42 == answer) {
  doSomething();
}

is preferable to

if (answer == 42) {
  doSomething();
}

in C-based languages. The reason for this is that if you accidentally put a single equals sign:

if (42 = answer) {
  doSomething();
}

will give you a compiler error, but

if (answer = 42) {
  doSomething();
}

might not, and would definitely introduce a bug that might be hard to track down. So who knows, maybe the person/people who set up the unit testing framework were used to thinking of equality tests in this way -- or they were copying other unit testing frameworks that were already set up this way.

Solution 5 - Unit Testing

I think it's because JUnit was the precursor of most unit testing frameworks (not that it was the first unit testing framework, but it kicked off an explosion in unit testing). Since JUnit did it that way, all the subsequent frameworks copied this form and it became a convention.

why did JUnit do it that way? I don't know, ask Kent Beck!

Solution 6 - Unit Testing

My view for this would be to avoid any exceptions eg: 42.equals(null) vs null.equals(42)

where 42 is expected null is actual

Solution 7 - Unit Testing

Well they had to pick one convention. If you want to reverse it try the Hamcrest matchers. They are meant to help increase readability. Here is a basic sample:

import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.hamcrest.core.Is.is;

public HamcrestTest{
   @Test
   public void matcherShouldWork(){
	   assertThat(   Math.pow( 2, 3 ),  is( 8 )  );
   }
}

Solution 8 - Unit Testing

Surely it makes logical sense to put the expected value first, as it's the first known value.

Think about it in the context of manual tests. A manual test will have the expected value written in, with the actual value recorded afterwards.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSebastiaan MView Question on Stackoverflow
Solution 1 - Unit Testingk.mView Answer on Stackoverflow
Solution 2 - Unit TestingRiccardo TrammaView Answer on Stackoverflow
Solution 3 - Unit TestingTomasz NurkiewiczView Answer on Stackoverflow
Solution 4 - Unit TestingeeeeaaiiView Answer on Stackoverflow
Solution 5 - Unit TestingJonny CundallView Answer on Stackoverflow
Solution 6 - Unit TestingmsatyaView Answer on Stackoverflow
Solution 7 - Unit TestingSledView Answer on Stackoverflow
Solution 8 - Unit Testingamarsha4View Answer on Stackoverflow