JUnit defines many methods that are designed to confirm the outcome of methods. In general writing tests for the expected outcomes are usually very easy, because you know what you want your program to do.
For instance: When looking for a student with a certain id, you expect the search method to find the correct student.
When designing tests it is important to also try and come up with situations that might go wrong. And then to write tests that confirm that the result are indeed incorrect.
For instance: What will you expect when the list doesn’t contain that student? Or when the list is empty? Or when the list is a null reference?
You must write tests that confirm the expected answer in those cases as well.
To indicate that a method is intended as a unittest. The @Test
annotation is
added. From this test function other (non-test) functions may be called. But
this annotation adds the method to the list of tests.
When designing tests please apply the following rule of thumb:
Each test method should test “one single concept”.
When testing you will often want to confirm that the correct outcome was
calculated. Of that the correct item was retrieved from the list. For that
purpose you will use the assertEquals
method:
assertEquals(Object expected, Object actualOutcome);
or
assertNotEquals(Object notThisValue, Object actualOutcome);
For instance:
assertEquals(15, Rectangle.calculateSurface(3,5));
equals
methodThe equals will check for equality using the actual equals
method
that your class overrides. If you didn’t override the equals method
the only “equal” instance will be the very same instance:
Person frederik = new Person("Frederik", "Bonte");
Person copy_FB = new Person("Frederik", "Bonte");
// Will be set to FALSE!!! (Because they are two different references.)
boolean nope = frederik.equals(copy_FB);
boolean duh = frederik.equals(frederik); // Same for copy_FB
So, don’t forget to actually override the equals
function where needed.
To check if the object is the very same there is an actual assertion:
assertSame(Object expected, Object actual);
This assertion only succeeds when both variables store the exact same reference.
Try to avoid using a calculation for the expected value.
Your expected value should preferably be a constant value!
assertEquals(15, Rectangle.calculateSurface(3,5));
In this case I didn’t do the following:
assertEquals(3*5, Rectangle.calculateSurface(3,5));
In this case it is absolutely silly to make this distinction but consider a more complex situation.
assertEquals(???, difficultCalculation(list, 3.141));
Apparently this “difficult calculation” does something tricky with a list and a double value. It doesn’t really matter what that is, but the point is how will you come up with the correct value.
You might be tempted to write some code to figure that value out. But please be wary here. You might end up with similar (or the same) code that is actually used in the function. In that case you run the risk of making the same mistake. You are then testing the code against a copy of itself:
assertEquals(Rectangle.calculateSurface(3,5), Rectangle.calculateSurface(3,5));
This code will never register a mistake in the calculate surface function.
In conclusion: try to find a way in which you can hard code the expected value.
For comparing a double outcome please provide a “margin of error”:
double myPi = 22.0d / 7.0d; // Don't use this in real life!
assertEquals(3.14159, myPi, 0.001);
In this case, when the difference is less than 0.001, the assertion will succeed.
In cases when the expected value is meant to be null you can use this assertion:
assertNull(Object nullValue);
or inversely:
assertNotNull(Object notNullValue);
This clearly marks a point in your test where you intend certain variables to have a null value after going through some procedure.
Personally I prefer to check for not null before checking other values:
Object result = createObject(someInput);
assertNotNull(result);
assertEquals(15, result.getAge());
Since I am not responsible for the content of the “createObject” function I don’t care if it is able to return a null value. I want to communicate that my test required the value not to be null.
This ensures that my test causes and assertions failure when my assumptions are wrong, instead of a null pointer exception.
This should hopefully mean that other tests also fail. If they don’t then there is a miscommunication within my team of developers (or with yourself).
For boolean confirmations there are the two methods:
assertTrue(boolean expectTrue);
and
assertFalse(boolean expectFalse);
There are many more useful assert functions. But to start your unit testing journey these three are a good beginning. For more assertions please use the junit documentation.