【问题标题】:test a function using assert c++使用断言 C++ 测试函数
【发布时间】:2026-02-13 14:45:01
【问题描述】:

我想使用断言测试 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";
}

}

【问题讨论】:

  • assert 不会抛出异常,它只是在打印出一些东西后终止程序。
  • 另外,您应该将throw 与派生自std::exception 的内容一起使用,而不是使用const char* 文字。
  • assert(true) 是多余的。

标签: c++ try-catch assert throw greatest-common-divisor


【解决方案1】:

“我想使用断言测试 gcd 函数,但我不知道如何捕获异常(并防止程序崩溃)。”

正如reference documentation 中所述,assert() 是一个实现定义的宏(强调我的):

#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition) /*implementation defined*/
#endif

如果未定义NDEBUG,则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);
}

这是fully working version。并且 another sample 未通过测试用例。


此外,由于assert() 将始终中止您的test_gcd() 函数,因此进行单元测试有点乏味。我建议使用一个体面的单元测试框架,在那里您可以更好地控制测试期望并运行各种测试用例。例如。使用Google Test 之类的东西(它将有一个EXPECT_TRUE() 的实现)。

【讨论】: