Утверждения в стиле Printf с использованием CPPUnit

Есть ли в CPPUnit какие-либо функции, которые позволили бы мне выполнять утверждения в стиле printf? Например:

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

Я знаю, что это недействительный CPPUNIT_ASSERT — я просто использую это как пример.

Я нашел CPPUNIT_ASSERT_MESSAGE(message,condition), который принимает строку, а затем условие для оценки, но не повезло получить значение в утверждении.


person larrylampco    schedule 19.08.2013    source источник
comment
почему вы не можете просто использовать sprintf, чтобы поместить значение в строку message, а затем вызвать с ним CPPUNIT_ASSERT_MESSAGE(message,condition)?   -  person Paul Evans    schedule 19.08.2013
comment
@PaulEvans Я пытался обойти использование функций в стиле C в C++.   -  person larrylampco    schedule 20.08.2013


Ответы (3)


Вы должны быть в состоянии сделать что-то вроде этого:

#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);
person jxh    schedule 19.08.2013
comment
Зачем тебе do {}while (0) ? - person sasha.sochka; 20.08.2013
comment
@sasha.sochka do{}while(0) делает строки одним составным оператором. ';' отлично завершит это, и макрос не зависит от окружающего контекста. - person harper; 20.08.2013
comment
@jxh Итак, я думаю, что ответ отрицательный, и мне нужно создать свой собственный макрос? - person larrylampco; 21.08.2013
comment
@larrylampco: я не нашел ни одной существующей функции CPPUnit, которая обеспечивала бы форматированные утверждения. - person jxh; 21.08.2013

Я использую selfdefined assert для печати всей необходимой информации:

#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() );

or

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

Пожалуйста, используйте CPPUNIT_ASSERT_EQUAL, который принимает фактическое и ожидаемое значение. Это в значительной степени устраняет необходимость форматирования строки, так как фактические и ожидаемые значения будут напечатаны в сообщении об ошибке.

Вы также можете скопировать реализацию этого макроса и функции, которую он вызывает, и добавить дополнительные макросы для других типов сравнений. Еще одна идея, которую я опробовал, заключалась в использовании перегрузки операторов для извлечения значения из выражения. Это (ab) использует перегрузку оператора для захвата выражения, но, возможно, это кажется слишком хакерским. Я включил его, чтобы дать вам представление о том, что возможно, но не рекомендовал бы его использовать:

#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;
}
person Dark Falcon    schedule 19.08.2013
comment
Мне нравится этот макрос, однако он не допускает никаких утверждений, кроме равенства. Как вы используете больше или меньше чем? - person larrylampco; 20.08.2013
comment
Я добавил несколько дополнительных комментариев. - person Dark Falcon; 20.08.2013