По моему (ограниченному) опыту первый вариант немного безопаснее. В тестовом примере вы тестируете только предопределенные входные данные и сравниваете результат, это работает хорошо до тех пор, пока все возможные крайние случаи были проверены. Первый вариант просто проверяет каждый ввод и, таким образом, проверяет «живые» значения, он очень быстро отфильтровывает ошибки, однако он снижает производительность.
In Code Complete Стив Макконнелл узнает, что первый метод может быть успешно использован для фильтрации ошибок в debug сборке. В сборке релиза вы можете отфильтровать все утверждения (например, с флагом компилятора), чтобы получить дополнительную производительность.
На мой взгляд, лучше всего использовать оба метода:
Способ 1 для отлова недопустимых значений
int doWonderfulThings(const int* fantasticData)
{
ASSERT(fantasticData);
ASSERTNOTEQUAL(0, fantasticData)
return WOW_VALUE / fantasticData;
}
и метод 2 для проверки граничных случаев алгоритма.
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));
}