TotT: Data Driven Traps!
September 4th, 2008 | Published in Google Testing
const struct {const char* word; bool is_word;} test_data[] = {
{"milk", true}, {"centre", false}, {"jklm", false},
};
TEST(IsWordTest, TestEverything) {
for (int i = 0; i
EXPECT_EQ(test_data[i].is_word, IsWord(test_data[i].word));
}
This keeps the test code short and makes it easy to add new tests but makes it hard to identify a failing test assertion (and to get the debugger to stop in the right place). As your code grows the test data tends to grow faster than linearly. For example, if you add a parameter called locale to IsWord, the test could become:
Locale LOCALES[] = { Word::US, Word::UK, Word::France, ... };
const struct {const char* word; bool is_word[NUM_LOCALES];} data[] = {
{"milk", {true, true, false, ...}}, // one bool per language
{"centre", {false, true, true, ...}},
{"jklm", {false, false, false, ...}}
};
TEST(IsWordTest, TestEverything) {
for (int i = 0; i
for (int j = 0; j
EXPECT_EQ(data[i].is_word[j], IsWord(data[i].word, LOCALES[i]));
}
The change was relatively easy to make: change the data structure, fill in the boolean values for other locales and add a loop to the test code. But even this small changed has made the test harder to read and slower as it repeats potentially unnecessary checks. In addition, both the test AND the code have changed. How do you know the test is not broken? (Actually, it is broken. Can you see the bug?) By contrast, keeping the data in the test gives us:
TEST(IsWordTest, IsWordInMultipleLocales) {
EXPECT_TRUE(IsWord("milk", Word::UK));
EXPECT_TRUE(IsWord("milk", Word::US));
EXPECT_FALSE(IsWord("milk", Word::France));
}
TEST(IsWordTest, IsWordWithNonExistentWord) { // 'jklm' test is not repeated
EXPECT_FALSE(IsWord("jklm", Word::US)); // as it uses the same code path
}
The difference between these two code snippets is minor but real-life data-driven tests quickly become unmanageable. A complete example would not fit on this page but if you look at your code base, you will find a few specimens lurking in some (not-so) forgotten test classes. They can be identified by their large size, vague names and the fact that they provide little to no information about why they fail.
Remember to download this episode of Testing on the Toilet and post it in your office.