正确处理异常的测试用例类

时间:2019-02-18 17:25:42

标签: c++ exception

我为自动测试编写了一个简单的C ++类(我尽可能简化了该问题)

class TestCase {
    int passed, failed; // keeps the number of tests passed/failed so far.

public:
    TestCase(): passed(0), failed(0) {}

    void print() const {
        int total = passed+failed;
        int grade = (total==0? 0: 100*passed/total);
        cout << "\n*** Right: " << passed << ". Wrong: " << failed << ". Grade: " << grade << " ***\n";
    }

    TestCase& check_equal(int actual, int expected) {
        if (actual==expected) {
            passed++;
        } else {
            failed++;
            cout << "The result is " << actual << " but it should equal " << expected << "!" << endl;
        }
        return *this;
    }
};

我这样使用:

TestCase testcase;
testcase
.check_equal(sum(1,2), 3)
.check_equal(factorial(5), 120)
...
.check_equal(fibonacci(4), 3)
.print();

只要检查的函数不引发异常,它就可以正常工作。如果“ check_equal”中的任何函数引发异常-不打印任何内容。我可以将整个块包装在try&catch中,例如:

TestCase testcase;
try {
    testcase
    .check_equal(sum(1,2), 3)
    .check_equal(factorial(5), 120)
    ...
    .check_equal(fibonacci(4), 3)
} catch (...) {
   testcase.print();
}

但是,如果第一次检查成功并且第二次检查抛出异常,则等级为100,因为通过= 1,失败= 0,总计= 1。这显然是错误的。

我当然可以决定在出现异常的情况下,等级为0,但这也是错误的,因为某些检查确实成功了。 我希望成绩例如到目前为止的成功次数除以测试总数。但是,该类不知道测试的总数,因为该异常发生在查看所有测试之前!

一种可能的解决方案是将传递给check_equal的每个函数调用包装在try-catch块中,但是当有许多小型测试时,这变得非常麻烦。

修复此类的优雅解决方案是什么?

1 个答案:

答案 0 :(得分:2)

您可以做的是推迟初始化actual的函数调用以在函数内部进行。然后check_equal可以处理该异常,如果确实发生异常,则将其取消(通过捕获),然后记录故障。有几种不同的处理方式,但一种方式是使用lambda之类的

template <typename Func>
TestCase& check_equal(Func actual, int expected) {
    try {
        auto act = actual();
        if (act==expected) {
            passed++;
        } else {
            failed++;
            cout << "The result is " << act << " but it should equal " << expected << "!" << endl;
        }
    }
    catch(...) {
        failed++;
    }
    return *this;
}

您会这样称呼

TestCase testcase;
testcase
.check_equal([](){return sum(1,2);}, 3)
.check_equal([](){return factorial(5);}, 120)
...
.check_equal([](){return fibonacci(4);}, 3)
.print();

您甚至可以使用宏删除样板

#define FUNCTOR(func) [](){return func;}

TestCase testcase;
testcase
.check_equal(FUNCTOR(sum(1,2)), 3)
.check_equal(FUNCTOR(factorial(5)), 120)
...
.check_equal(FUNCTOR(fibonacci(4)), 3)
.print();