【问题标题】:Exceptions and BDD in C++ - Catch libraryC++ 中的异常和 BDD - Catch 库
【发布时间】:2014-04-05 09:11:29
【问题描述】:

到目前为止,我一直在使用 Boost.Test,但现在正在考虑将 BDD 与 Catch 一起使用,但我在找出处理异常的好方法时遇到了一些麻烦。假设我有这样的测试:

SCENARIO("connection handling", "[network]") {
    boost::asio::io_service io;
    GIVEN("a connection that should fail") {
        connection::ptr conn = connection::create(new fake_provider<connection_refused>(io));
        WHEN("trying to connect") {
            conn->connect("localhost", 1);
            THEN("connection was refused") {
                some stuff to verify exception code
                REQUIRE(conn->connected() == false);
            }
        }
    }
}

现在我想知道如何处理 connect() 会以一种很好的方式抛出异常的事实。我想我可以将异常保存并存储在 try-catch 中并在 THEN 下进行验证,但这似乎不太好。在我的 Boost.Test 测试用例中,我这样做了:

bool error_is_connection_refused(boost::system::system_error ex) {
    return ex.code() == boost::system::errc::connection_refused;
}
BOOST_AUTO_TEST_CASE(connect)
{
    connection::ptr conn_refuse = connection::create(new fake_provider<connection_refused>(*io_ptr));
    BOOST_REQUIRE_EXCEPTION(conn_refuse->connect("localhost", 1),
                            boost::system::system_error,
                            error_is_connection_refused);
    BOOST_REQUIRE_EQUAL(conn_refuse->connected(), false);
}

但这似乎不是很 BDD。人们在使用 BDD 测试时通常如何处理抛出异常的代码?

【问题讨论】:

  • 对我来说,您的 Boost Test 解决方案看起来不错。与该有效解决方案相比,您要解决的问题是什么?
  • 实际上没什么大不了的,我必须解决一些小问题才能让 boost.test 工作(例如,在 jenkins 中获取报告,因为 boost.test 无法输出 jUnit兼容的 xml),并且似乎 boost.test 不再被开发/维护。并在听到一些关于 BDD 之后对它感到好奇。我会稍微更新一下问题。
  • 我认为 Boost.Test 非常成熟——它不是“维护”的,因为它不需要。你可以打赌,如果其中有彻底的错误,他们会得到修复,因为 Boost 人员是官方维护者,他们反应迅速。这是一个关于如何让 Jenkins 理解 Boost Test 输出的问题:stackoverflow.com/questions/16537914/…
  • 啊,好的。很公平 :) 我有 boost.test 来理解覆盖率和诸如此类的输出,所以这已经修复了。不过,我仍然很好奇 BDD 处理异常的方式是什么。

标签: c++ unit-testing bdd catch-unit-test


【解决方案1】:

我有点晚了,因为我刚刚注意到了 catch-unit-test 标签:-)

目前你可以这样做:

REQUIRE_THROWS( <expr> );

或测试特定异常类型

REQUIRE_THROWS_AS( <type>, <expr> );

如果您想验证异常消息的内容...目前没有办法在不自己捕获的情况下做到这一点。不过,这是我考虑添加的一项功能。

【讨论】:

  • 你能在 OP 的例子中展示这个吗? IE。我想这必须放在WHEN("trying to connect") 块的顶部,而不是在 OP 发表评论的THEN("connection was refused") 块中(并且感觉更自然)。 (Re:断言异常消息:我在 phpUnit 中使用此工具 - 我喜欢它有效地描述抛出异常的原因,因此有助于在 6 个月后阅读测试时理解测试。)
  • 看起来像这样:REQUIRE_THROWS_AS( boost::system::system_error, conn-&gt;connect("localhost", 1) );
【解决方案2】:

这是 philsquared

建议的验证异常内容的方法
#include <stdexcept>
#include "catch.hpp"

void my_func(double v) 
{
    // ...
}

TEST_CASE("wrong params", "[tag]") {
    SECTION("wrong rate") {
        try {
            my_func(1.1);  // must be in range [0..1]
            REQUIRE_FALSE("must raise issue about rate");
        }
        catch(const std::invalid_argument& e) {
            std::string str (e.what());
            std::string str2 ("rate");
            REQUIRE_FALSE(str.find(str2) == std::string::npos);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    相关资源
    最近更新 更多