1 Unit Testing handout
1 Unit Testing handout
Benefits2
• Find problems early: test driven development requires unit tests to be written before the code.
Even if written after, unit tests save tremendous amount of time by finding quickly the location
of the problem.
• Facilitates change: Unit testing allows the programmer to refactor code at a later date, and
make sure the module still works correctly (e.g., in regression testing). The procedure is to write
test cases for all functions and methods so that whenever a change causes a fault, it can be
quickly identified and fixed. Readily available unit tests make it easy for the programmer to
check whether a piece of code is still working properly.
• Simplifies integration:
• Documentation: Living documentation of the systems.
1
From http://artofunittesting.com/definition-of-a-unit-test/
2
From https://en.wikipedia.org/wiki/Unit_testing
• Design: When software is developed using a test-driven approach, the unit test may take the
place of formal design. Each unit test can be seen as a design element specifying classes,
methods, and observable behaviour.
• Separation of interface from implementation: Because some classes may have references to
other classes, testing a class can frequently spill over into testing another class. A common
example of this is classes that depend on a database: in order to test the class, the tester often
writes code that interacts with the database. This is a mistake, because a unit test should usually
not go outside of its own class boundary, and especially should not cross such process/network
boundaries because this can introduce unacceptable performance problems to the unit test-
suite. Crossing such unit boundaries turns unit tests into integration tests, and when test cases
fail, makes it less clear which component is causing the failure.
Instead, the software developer should create an abstract interface around the database
queries, and then implement that interface with their own mock object. By abstracting this
necessary attachment from the code (temporarily reducing the net effective coupling), the
independent unit can be more thoroughly tested than may have been previously achieved. This
results in a higher quality unit that is also more maintainable.
Example
Souce code: Math.java Test Code: MathTest.java
public class Math { import static org.junit.jupiter.api.Assertions.*;
static public int add(int a, int b) { import org.junit.jupiter.api.Test;
return a + b;
} class MathTest {
} @Test
void testAddStatic() {
int num1 = 3;
int num2 = 2;
int total = 5;
int sum = 0;
sum = Math.add(num1, num2);
assertEquals(sum, total);
}
}
Note that you have to add JUnit 5 library to the build path. Eclipse proposes to do that for you if you right-
click and select new JUnit Test Case.
to obtain
i
You can see that the coverage is only 88.5%. The missing line is public class Math. That makes sense since
we called our class using the static method Math.add without implementing any object. Add a nonstatic
test as below and verify that you now reach 100% coverage.
Note that there is code duplication. Refactor your code to remove it by taking advantage of the
@BeforeEach annotation.
A list of Annotations is available at https://junit.org/junit5/docs/current/user-guide/#writing-tests
A very interesting annotation is @ParameterizedTest. It allows a very compact writing of tests, for
example:
References:i
JUnit Tutorial: http://www.vogella.com/articles/JUnit/article.html
The Art of Unit Testing: http://artofunittesting.com/
Wikipedia Unit Testing: https://en.wikipedia.org/wiki/Unit_testing
Wikipedia Mock Object: https://en.wikipedia.org/wiki/Mock_object