Я хочу протестировать функцию gcd с помощью утверждений, но я не знаю, как перехватить исключение (и предотвратить сбой программы).
int gcd(int a, int b) {
if(a<0 || b<0) {
throw "Illegal argument";
}
if(a==0 || b==0)
return a+b;
while(a!=b) {
if(a>b) {
a = a - b;
}
else {
b = b - a;
}
}
return a;
}
void test_gcd() {
assert(gcd(16,24) == 8);
assert(gcd(0, 19) == 19);
try {
gcd(5, -15);
assert(false);
} catch (char* s) {
assert(true);
cout << "Illegal";
}
}
«Я хочу проверить функцию gcd, используя утверждения, но я не знаю, как поймать исключение (и предотвратить сбой программы). «
Как указано в справочная документация assert()
является макросом, определяемым реализацией (выделено мной):
#ifdef NDEBUG #define assert(condition) ((void)0) #else #define assert(condition) /*implementation defined*/ #endif
Если
NDEBUG
не определяется, тоassert
проверяет, сравнивается ли его аргумент (который должен иметь скалярный тип) равным нулю. Если это так, assert выводит специфическую для реализации диагностическую информацию на стандартный вывод ошибок и звонкиstd::abort
. Диагностическая информация должна включать текст выражения, а также значения стандартных макросов__FILE__
,__LINE__
и стандартная переменная__func__
,
таким образом assert()
не исключение Вы можете поймать. Чтобы проверить свой код и исправить использование исключений, у вас должно быть что-то вроде следующего, где expect_true()
это то, что печатает сообщение, если параметр оценивается как false
и не abort()
ваша программа:
int gcd(int a, int b) {
if(a<0 || b<0) {
throw std::invalid_argument("a and b must be negative values");
}
// ...
}
#define expect_true(arg) \
do { \
if(!(arg)) { \
std::cout << "Unexpected false at " \
<< __FILE__ << ", " << __LINE__ << ", " << __func__ << ": " \
<< #arg \
<< std::endl; } \
} while(false);
void test_gcd() {
expect_true(gcd(16,24) == 8);
expect_true(gcd(0, 19) == 19);
bool exceptionCaught = false;
try {
gcd(5, -15);
} catch (const std::invalid_argument& ex) {
cout << "Illegal as expected" << endl;
exceptionCaught = true;
}
expect_true(exceptionCaught);
}
Вот полностью рабочая версия. А также другой образец провал теста
Также с assert()
всегда прервет ваш test_gcd()
функция, это немного утомительный способ сделать модульное тестирование. Я бы порекомендовал использовать подходящую среду модульного тестирования, где у вас есть больший контроль над ожиданиями тестирования и запуск различных тестовых случаев. Например. использовать что-то вроде Google Test (который будет иметь реализацию для EXPECT_TRUE()
).