Test-Driven Development: A walkthrough using Java
What
Is
TDD ?
Why Developers don't use at first?
"There is no time to write unit tests"
TDD
"Haven't used before and my code is good"
"It won't make my code bullet-proof"
Requires a paradigm shift
It's Simple but...
is not just about Testing.
TDD
Better structure in code
Reduce time debugging
Make a plan, then code
TDD
Best Practices.
Naming Conventions :
Place Test and Implementation in different packages.
Use descriptive names for methods.
public final void whenMoreThan2NumbersAreUsedThenExceptionIsThrown() {
StringCalculator.add("1,2,3");
}
Test
Processes:
- Write tests before implementation code.
- Rerun all tests every time implementation code changes.
- All test should pass before new test is written.
- Refactor only after all test are passing.
Development Practices:
Write simplest code to pass the test.
Assertions goes first.
Minimize assertions in each test
A practical example:
List of requirements to make a String Calculator:
- Create a simple String calculator with a method int Add(string numbers)
- The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0) for example “” or “1” or “1,2”
- Allow the Add method to handle an unknown amount of numbers
Requirement 1:
The method can take up to 2 string numbers, each one separated by a comma(,)
class CalculatorTest extends groovy.util.GroovyTestCase {
@Test(expected = RuntimeException.class)
public final void whenMoreThan2NumbersAreUsedThrowException() {
StringCalculator.add("1,2,3");
}
@Test
public final void when2NumbersAreUsedDoNotThrowException() {
StringCalculator.add("1,2");
Assert.assertTrue(true);
}
@Test(expected = RuntimeException.class)
public final void whenNonNumberIsUsedThenExceptionIsThrown() {
StringCalculator.add("1,X");
}
}
Test:
The method can take up to 2 string numbers, each one separated by a comma(,)
public class StringCalculator1 {
public static final void add(final String numbers) {
String[] numbersArray = numbers.split(",");
if (numbersArray.length > 2) {
throw new RuntimeException("Up to 2 numbers separated by comma (,) are allowed");
} else {
for (String number : numbersArray) {
Integer.parseInt(number); // If it is not a number, parseInt will throw an exception
}
}
}
}
Implementation:
Requirement 2:
@Test
public final void whenEmptyStringIsUsedThenReturnValueIs0() {
Assert.assertEquals(0, StringCalculator.add(""));
}
Test
public static final int add(final String numbers) { // Changed void to int
String[] numbersArray = numbers.split(",");
if (numbersArray.length > 2) {
throw new RuntimeException("Up to 2 numbers separated by comma (,) are allowed");
} else {
for (String number : numbersArray) {
if (!number.isEmpty()) {
Integer.parseInt(number);
}
}
}
return 0; // Added return
}
Implementation
For an empty string the method will return 0
TDD
Let's see
in action!
Text
Monday Talks 03.09.15
By Luis Hernandez
Monday Talks 03.09.15
- 642