【问题标题】:Printf-Style Assertions using CPPUnit使用 CPPUnit 的 Printf 样式断言
【发布时间】:2013-08-19 16:53:31
【问题描述】:

CPPUnit 是否有任何功能可以让我进行printf 风格的断言?例如:

CPPUNIT_ASSERT("Actual size: %d", p->GetSize(), p->GetSize() == 0);

我知道这不是有效的 CPPUNIT_ASSERT - 我只是以此为例。

我找到了CPPUNIT_ASSERT_MESSAGE(message,condition),它接受一个字符串,然后是评估条件,但没有运气将值放入断言中。

【问题讨论】:

  • 为什么不能直接使用sprintf 将值放入message 字符串,然后用它调用CPPUNIT_ASSERT_MESSAGE(message,condition)
  • @PaulEvans 我试图在 C++ 中使用 C 风格的函数。

标签: c++ cppunit


【解决方案1】:

你应该可以做这样的事情:

#define CPPUNIT_ASSERT_STREAM(MSG, CONDITION) \
    do { \
        std::ostringstream oss; \
        CPPUNIT_ASSERT_MESSAGE(\
            static_cast<std::ostringstream &>(oss << MSG).str(), \
            CONDITION); \
    } while (0)

CPPUNIT_ASSERT_STREAM("Actual size: " << p->GetSize(), p->GetSize() == 0);

上面的宏也可以和Boost.format结合:

CPPUNIT_ASSERT_STREAM(boost::format("Actual size: %d") % p->GetSize(),
                      p->GetSize() == 0);

【讨论】:

  • 为什么需要do {}while (0)
  • @sasha.sochka do{}while(0) 将这些行变成一个复合语句。这 ';'将完美地完成此操作,并且宏不依赖于周围的上下文。
  • @jxh 所以我想答案是否定的,我必须创建自己的宏?
  • @larrylampco:我没有找到任何提供格式化断言的 CPPUnit 现有功能。
【解决方案2】:

我使用自定义断言打印所有需要的信息:

#ifdef NDEBUG
#define ASSERT(v, msg)
#else
#define ASSERT(v, msg) \
if (v) {} else { \
  std::cerr << __FILE__ << ":" << __LINE__ << " assertion failed: " \
            << #v << " = " << (v) << "\n" << msg << std::endl; \
  abort(); \
}
#endif

使用方法:

#include <iostream>
...
ASSERT( p->GetSize() == 0, p->GetSize() );

ASSERT( p->GetSize() == 0, "Actual size: " << p->GetSize() << " Actual size * 2: " << p->GetSize()*2 );

【讨论】:

    【解决方案3】:

    请使用CPPUNIT_ASSERT_EQUAL,它采用实际值和预期值。这几乎消除了格式化字符串的需要,因为实际值和预期值将打印在失败消息中。

    您还可以复制此宏的实现及其调用的函数,并为其他类型的比较添加其他宏。我尝试的另一个想法是使用运算符重载从表达式中捕获值。这个 (ab) 使用运算符重载来捕获表达式,但它似乎有点太 hackish。我将它包含在内是为了让您了解可能的情况,但不建议使用它:

    #include <iostream>
    #include <sstream>
    
    class ExpressionPrinter
    {
    public:
      std::ostringstream result;
    
      template<typename T> ExpressionPrinter& operator<<(const T& other)
      {
        result << other;
        return *this;
      }
    
      template<typename T> ExpressionPrinter& operator<(const T& other)
      {
        result << " < ";
        result << other;
        return *this;
      }
    
      template<typename T> ExpressionPrinter& operator<=(const T& other)
      {
        result << " <= ";
        result << other;
        return *this;
      }
    
      template<typename T> ExpressionPrinter& operator>(const T& other)
      {
        result << " > ";
        result << other;
        return *this;
      }
    
      template<typename T> ExpressionPrinter& operator>=(const T& other)
      {
        result << " >= ";
        result << other;
        return *this;
      }
    
      template<typename T> ExpressionPrinter& operator==(const T& other)
      {
        result << " == ";
        result << other;
        return *this;
      }
    
      template<typename T> ExpressionPrinter& operator!=(const T& other)
      {
        result << " != ";
        result << other;
        return *this;
      }
    };
    
    #define ASSERT(X) doAssert((X), (ExpressionPrinter() << X));
    
    void doAssert(bool result, const ExpressionPrinter& message)
    {
      std::cout << "Result: " << result << ", Expression: " << message.result.str() << std::endl;
    }
    
    int main()
    {
      int i = 1, j = 2;
    
      ASSERT(i < j);
    
      return 0;
    }
    

    【讨论】:

    • 我确实喜欢这个宏,但是它不允许除相等之外的断言。如何使用大于或小于?
    • 我添加了一些额外的 cmets。
    【解决方案4】:
    #include <iostream>
    ...
    ASSERT( p->GetSize() == 0, p->GetSize() );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-20
      • 2015-11-13
      相关资源
      最近更新 更多