Use Meaningful Assertions

 class​ CruiseControlTest {
 
  @Test
 void​ setPlanetarySpeedIs7667() {
  CruiseControl cruiseControl = ​new​ CruiseControl();
 
  cruiseControl.setPreset(SpeedPreset.PLANETARY_SPEED);
 
» Assertions.assertTrue(7667 == cruiseControl.getTargetSpeedKmh());
  }
 }

The most basic assertion you can find in JUnit is assertTrue(). In the end, everything boils down to a Boolean value, whether a condition holds or doesn’t. Interpreting Boolean expressions is no problem at all for Java, but you can make the life of your fellow developer a lot easier by writing assertions in a way that’s more accessible. And you won’t usually do this with assertTrue().

Take a look at the code above. The assertion checks that the value of targetSpeedKmh is identical to 7667. Checking for identity with the == operator is fine here because we compare only primitive types: two ints. With objects, you’d use equals() instead.

The test is functionally correct, but there’s a problem that surfaces when the test fails. If that happens, we’ll get a stack trace with a java.lang.AssertionError that contains the class and line number of the failed assertion, but without any message. So we only know which assertion failed, not why it failed.

That message (or rather the lack of one) isn’t helpful when you’re trying to make sense of what’s broken. You’re not directed toward the location of a bug. That’s because the assertion simply doesn’t care that two values are compared with each other—it only cares that some Boolean value should be true but is false. So it’s simply not possible to describe the failed assertion in more detail.

So how can we provide more information with the assertion so that we get better error messages?

 class​ CruiseControlTest {
 
  @Test
 void​ setPlanetarySpeedIs7667() {
  CruiseControl cruiseControl = ​new​ CruiseControl();
 
  cruiseControl.setPreset(SpeedPreset.PLANETARY_SPEED);
 
» Assertions.assertEquals(7667, cruiseControl.getTargetSpeedKmh());
  }
 }

The solution is actually quite simple. We use a different assertion, one that’s made for checking if two values are the same: assertEquals(). With this assertion, JUnit can provide a much better error message when the test fails. It’ll look like this:

expected: <7667> but was <1337>

That’s much more informative. Before, we only knew that the test failed. Now, we also know why the test fails: we expected the value to be equal to 7667, but actually it was 1337.

We’ve got to admit that it’s also possible to provide a more detailed message with assertTrue(). The big difference is that you have to build this message yourself and feed it into assertTrue(), which will display it in case of failure. That means that you’d have to build a message for every assertTrue() in our code base. It’s much better to just use an assertion that does this out of the box, such as assertEquals().

You might have recognized the message format. We used it in a comparison not so long ago: Explain Cause in Message. Exceptions can be very similar to failing tests in a sense, and the message format is very helpful for a developer to determine why something isn’t working as expected.

There’s much more in JUnit than assertEquals() and assertTrue(). Of course, you can also assertFalse(), assertNotEquals(), and assertSame(). You can check that arrays or data structures are equal (read: hold equal contents) with assertArrayEquals(), assertLinesMatch(), and assertIterableEquals(); that you’re able to group multiple assertions together with assertAll(); and that execution time is short enough with assertTimeout(). In any case, you should select the assertion that is the best fit for your test, because this will make for better messages.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.191.86