We all tend to write helper classes for testing, which clutters the test code and makes it harder to understand. A test should be like a story that you simply can read from top-down. I like test story better than fixture and I will use story and fixture interchangeable.
Why a Story Is More Powerful Than a Helper
If you have helpers you have code somewhere else, most often at the end of the test or even in another class where you hold all these helper utilities. If I read a test and I see method calls I tend to think that this is the code I test, but it is not. Helper utilities are also a sign that you probably need these utils also in your code and you should have tests for these utilities. As well helpers break the flow of your test story, it is like a reference to another story which you also should read before you can go on with this story. How awkward would that be in a book? Well, it is awkward as well in tests.
Unfortunately, this is hard to teach and to make visible why helper utilities are not a good thing.
When I write a test, I start with one single test and pack everything in that test I need, like calling methods, filling in entities, whatever is needed. Then I write a second test and do the same and after the third test, I put all the similarities into the setup method which is called before every test. And this holds the story. In Java JUnit5 it is the @BeforeEach annotation.
Let’s Jump Into The First Story
We base this blog article on the Test Driven Development Mantra. If not done yet read that first as it will give you a better understanding of the test refactoring we are going to make now.
We have two tests from that article (and maybe you did the exercise and wrote the next test with for "good afternoon")
@Mock
private DateTime dateTime
@Test
void shouldSayGoodMorningToTom() {
when(dateTime.getHourOfDay()).thenReturn(6);
assertEquals("Good morning Tom", sayHelloTo("Tom", new DateTime()));
}
@Test
void shouldSayGoodMorningToJerry() {
when(dateTime.getHourOfDay().thenReturn(6);
assertEquals("Good morning Jerry", sayHelloTo("Jerry", new DateTime()));
}
The similarities are very obvious here and you can make a good morning fixture out of it like this
public class GoodMorningTest {
@Mock
DateTime dateTime;
@BeforeEach
void setUp() {
when(dateTime.getHourOfDay().thenReturn(6);
}
@Test
void shouldSayGoodMorningToTom() {
assertEquals("Good morning Tom", sayHelloTo("Tom", new DateTime()));
}
@Test
void shouldSayGoodMorningToJerry() {
assertEquals("Good morning Jerry", sayHelloTo("Jerry", new DateTime()));
}
}
That’s it. You can read it top-down without any distractions. You have all together which makes tests very easy to read. Avoid helpers at all cost, it asks for troubles and confused programmers. And I’m well aware that this here is a very simple example, but honestly, most often it is not much more complicated than this here, test driven development favors simplicity.
Let me know if you have suggestions or questions in the comments below.
If you are interested in an online or onside workshop for test driven development write me an email artificials_ch@gmx.ch