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?

Original source