The bread and butter of a typical @Test
method involve something called assertions.
These assertions are found in the junit.org.Assert
class library, and each “assert” is a way to perform a specific test in JUnit testing.
Below are a couple of common assert methods (note: they all have a return type of void
):
Assert Method | Description |
---|---|
assertEquals(expected, actual) |
Checks if two values are equal |
assertNotEquals(expected, actual) |
Checks if two values are not equal |
assertTrue(boolean condition) |
Checks if a condition is true |
assertFalse(boolean condition) |
Checks if a condition is false |
assertNotNull(Object object) |
Checks if an object isn’t null |
assertNull(Object object) |
Checks if an object is null |
assertArrayEquals(expectedArray, actualArray) |
Checks if two arrays are equal |
When called, each assert is considered as a test case by the compiler, and any given assert can either pass or fail. A @Test
method can only pass if all test cases inside it pass. If any case fails, the whole test method will be marked red and considered a failed test.
Let’s walk through an example to best display how these asserts can be used.
Suppose we have a class object called Human
. We assign that object a name
, represented by a string, and an integer value to represent their hitpoints
upon creation.
Human sam = new Human(“Sam”, 100);
We want to test whether or not Sam gets properly created and also test a takeDamage()
method within the Human
class to ensure any damage taken is being recorded. Because this implies two different tests, let’s create two different test methods:
@Test public void testHuman() { Human sam = new Human(“Sam”, 100); assertEquals(100, sam.getHitpoints()); assertEquals(“Sam”, sam.getName()); } @Test public void testHumanTakeDamage() { Human sam = new Human(“Sam”, 100); assertEquals(100, sam.getHitpoints()); sam.takeDamage(10); assertEquals(90, sam.getHitpoints()); }
Take note that assertEquals()
has multiple variants of the same call to account for different variable types. For instance, assertEquals()
was used with both int
values and string
values for hitpoints
and name
respectively.
Each assert method is a tool a programmer can use to uniquely test their code. They typically follow the pattern of “expected value first,” then find the “actual” value in the second parameter to check against the expected.
There are a few exceptions that break this rule. When checking a boolean or an object’s existence, one parameter is used, and when double
and float
get involved, there is an optional third parameter that can be added. This third parameter can act as a delta
to establish a margin of error for a double
or float
value to fall within range of in order to be considered as “passable.” This is commonly used when code has random factors to its output. Something like that might look like this:
assertEquals(25.5, sam.calculateDamage(), 0.9);
This will pass if sam.calculateDamage()
returns a value anywhere within the range of 24.6
and 26.4
.
Note: @Test
can also detect an expected exception as well, allowing it to pass if the exception is detected and fail if no exception occurred:
@Test(expected = NullPointerException.class) void testNullPointerException() { // Test cases }
Instructions
Inside of TestExample.java is a @Test
method that references the class method inside of Example.java. The test cases are already written, but the method they test has nothing in it.
Let’s follow the “Red — Green — Refactor” mantra and make the tests fail.
In Example.java, make the factorial()
method return 0
.
Note: This program will expect all inputs to be non-negative.
Additionally, due to Codecademy’s implementation of JUnit, you’ll notice the imports are different in the code as well as the way an “assert” is performed. The way Hamcrest and standard JUnit perform an assert are virtually identical, they’re just written in different syntax.
You’ll need to use the Hamcrest imports and methods as shown in this example for the rest of the examples in this lesson, but be sure to note that it’s all functionally the same.
Hamcrest example of an assertEquals(expected, actual)
:
assertThat(actual, equalTo(expected));
The above will always use the following imports:
import static org.junit.Assert.fail; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.CoreMatchers.equalTo;
To compile and run your code, enter the following into the terminal:
$ ./run.bat
Run the test class, then Check Work.
Now that we’ve achieved the fabled “Red” of our mantra, let’s fix up that method and aim for “Green.”
factorial()
is an algorithm in math represented by the !
. For example, something like 3!
would result in an output of 6
. It does this by calculating the following formula: n! = (n)(n - 1)(n - 2)...(1)
.
Write the method to properly incorporate that algorithm.
To compile and run your code, enter the following into the terminal:
$ ./run.bat
Run the test class again, then Check Work. All the test cases should pass.
This particular algorithm in mathematics has one special case. If 0
is its input, it should return 1.
Write a test case beneath the others to check the computed output of factorial(0)
against the expected output of 1
.
To compile and run your code, enter the following into the terminal:
$ ./run.bat
Run the test and Check Work. Depending on how you wrote the method, this could either fail or pass on the first run. If it fails, fix the class method until all tests go green.