Test Cases VS ASSERTION statement
c++, defensive-programming, tdd
Solution
In my (limited) experience the first option is quite a bit safer. In a test-case you only test predefined input and compare the outcome, this works well as long as every possible edge-case has been checked. The first option just checks every input and thus tests the 'live' values, it filters out bugs real quickly, however it comes with a performance penalty.
In Code Complete Steve McConnell learns us the first method can be used successfully to filter out bugs in a debug build. In release build you can filter-out all assertions (for instance with a compiler flag) to get the extra performance.
In my opinion the best way is to use both methods:
Method 1 to catch illegal values
int doWonderfulThings(const int* fantasticData)
{
ASSERT(fantasticData);
ASSERTNOTEQUAL(0, fantasticData)
return WOW_VALUE / fantasticData;
}
and method 2 to test edge-cases of an algorithm.
int doMoreWonderfulThings(const int fantasticNumber)
{
int count = 100;
for(int i = 0; i < fantasticNumber; ++i) {
count += 10 * fantasticNumber;
}
return count;
}
TEST(TDD_Enjoy)
{
// Test lower edge
ASSERT_EQ(0, doMoreWonderfulThings(-1));
ASSERT_EQ(0, doMoreWonderfulThings(0));
ASSERT_EQ(110, doMoreWonderfulThings(1));
//Test some random values
ASSERT_EQ(350, doMoreWonderfulThings(5));
ASSERT_EQ(2350, doMoreWonderfulThings(15));
ASSERT_EQ(225100, doMoreWonderfulThings(150));
}
Problem
In my most C++ project I heavily used ASSERTION statement as following: ``` int doWonderfulThings(const int* fantasticData) { ASSERT(fantasticData); if(!fantasticData) return -1; // ,,, return WOW_VALUE; } ``` But TDD community seems like to enjoy doing something like this: ``` int doMoreWonderfulThings(const int* fantasticData) { if(!fantasticData) return ERROR_VALUE; // ... return AHA_VALUE; } TEST(TDD_Enjoy) { ASSERT_EQ(ERROR_VALUE, doMoreWonderfulThings(0L)); ASSERT_EQ(AHA_VALUE, doMoreWonderfulThings("Foo")); } ``` Just with my experiences first approaches let me remove so many subtle bugs. But TDD approaches are very smart idea to handle legacy codes. "Google" - they compare "FIRST METHOD" to "Walk the shore with life-vest, swim ocean without any safe guard". Which one is better? Which one makes software robust?