cppunit: передача в тест параметров
От: f123456  
Дата: 14.04.10 15:39
Оценка:
Начал изучать CppUnit и не могу понять как сделать хорошо.
Условие: конструктор класса может кинуть исключение. Это и хочется оттестировать.
Создал 2 метода: wrongConstructor1/2, которые проверяют нижнию и верхнюю границу.
Но как-то это не хорошо: если появится второй аргумент (хотябы bool), то придётся добавлять ещё 2 метода.

class CTestGame: public CPPUNIT_NS::TestFixture
{
   CPPUNIT_TEST_SUITE(CTestGame);
   CPPUNIT_TEST_EXCEPTION(wrongConstructor1, std::exception);
   CPPUNIT_TEST_EXCEPTION(wrongConstructor2, std::exception);
   ...
}

void CTestGame::wrongConstructor1()
{
   CGame game(g_nMinBoardDim - 1);
}

void CTestGame::wrongConstructor2()
{
   CGame game(g_nMaxBoardDim + 1);
}



Может кто знает, как написать что-то типа:

   CPPUNIT_TEST_EXCEPTION(wrongConstructor(true),  std::exception);
   CPPUNIT_TEST_EXCEPTION(wrongConstructor(false), std::exception);


Или есть другой паттерн, который может параметризовать вызовы wrongConstructor() ?
Re: cppunit: передача в тест параметров
От: dimchick Украина  
Дата: 14.04.10 15:56
Оценка:
Здравствуйте, f123456, Вы писали:

F>Начал изучать CppUnit и не могу понять как сделать хорошо.


F>Или есть другой паттерн, который может параметризовать вызовы wrongConstructor() ?


Может свой макрос сделать?
Re: cppunit: передача в тест параметров
От: uzhas Ниоткуда  
Дата: 14.04.10 17:30
Оценка: 7 (2)
Здравствуйте, f123456, Вы писали:

F>Начал изучать CppUnit и не могу понять как сделать хорошо.

F>Условие: конструктор класса может кинуть исключение. Это и хочется оттестировать.
F>Создал 2 метода: wrongConstructor1/2, которые проверяют нижнию и верхнюю границу.
F>Но как-то это не хорошо: если появится второй аргумент (хотябы bool), то придётся добавлять ещё 2 метода.
Есть такой подход — называйте тесты согласно тому, что они проверяют. Названия должны быть _утверждениями_, касающимися проектируемой системы. Тогда и в случае развала теста вы в логах увидите, что именно перестало работать. Поэтому добавить новые два метода — это вполне нормально.
Пример:
class CTestGame: public CPPUNIT_NS::TestFixture
{
  CPPUNIT_TEST_SUITE(CTestGame);
  CPPUNIT_TEST(GameWithLowDimCannotBeCreated);
  CPPUNIT_TEST(GameWithHighDimCannotBeCreated);
  CPPUNIT_TEST(GameWithSuperFlagIsConstructable);
   ...
}
void CTestGame::GameWithLowDimCannotBeCreated()
{
  CPPUNIT_ASSERT_THROW(CGame game(g_nMinBoardDim - 1), std::exception);
}

void CTestGame::GameWithHighDimCannotBeCreated()
{
  CPPUNIT_ASSERT_THROW(CGame game(g_nMaxBoardDim + 1), std::exception);
}

void CTestGame::GameWithSuperFlagIsConstructable()
{
  const bool superFlag = true;
  CPPUNIT_ASSERT_NO_THROW(CGame game(g_nMinBoardDim + 1, superFlag), std::exception);
}
Re: cppunit: передача в тест параметров
От: skeptik_  
Дата: 14.04.10 21:13
Оценка: -1 :)
Здравствуйте, f123456, Вы писали:

F>Начал изучать CppUnit и не могу понять как сделать хорошо.


Шоб було хорошо не надо изучать CppUnit. Boost.Test, UnitTest++, google test — наше всё.
Re[2]: cppunit: передача в тест параметров
От: f123456  
Дата: 15.04.10 05:13
Оценка:
Здравствуйте, uzhas, Вы писали:

Больщое спасибо за этот пример. Теперь мне понятно, как можно поставить обработку нескольких исключения в методе: отпала необходимость его параметризировать. =)

U>void CTestGame::TestConstructorBoundaries()
U>{
U>  CPPUNIT_ASSERT_THROW(CGame game(g_nMinBoardDim - 1), std::exception);
U>  CPPUNIT_ASSERT_THROW(CGame game(g_nMaxBoardDim + 1), std::exception);
U>}


Единственное, что компилятор не даёт вставлять std::exception: выдаёт ошибку
error C2312: 'const std::exception &' : is caught by 'const std::exception &' on line 27
Но это легко лечится указанием на std::runtime_error.

CPPUNIT_ASSERT_THROW(CGame game(g_nMaxBoardDim + 1), std::runtime_error);
Re[3]: cppunit: передача в тест параметров
От: uzhas Ниоткуда  
Дата: 15.04.10 05:55
Оценка:
Здравствуйте, f123456, Вы писали:

F>Единственное, что компилятор не даёт вставлять std::exception:

Действительно, к сожалению, CPPUNIT в своих макросах уже использует этот тип исключения
# define CPPUNIT_ASSERT_THROW_MESSAGE( message, expression, ExceptionType )   \
   do {                                                                       \
      bool cpputCorrectExceptionThrown_ = false;                              \
      CPPUNIT_NS::Message cpputMsg_( "expected exception not thrown" );       \
      cpputMsg_.addDetail( message );                                         \
      cpputMsg_.addDetail( "Expected: "                                       \
                           CPPUNIT_GET_PARAMETER_STRING( ExceptionType ) );   \
                                                                              \
      try {                                                                   \
         expression;                                                          \
      } catch ( const ExceptionType & ) {                                     \
         cpputCorrectExceptionThrown_ = true;                                 \
      } catch ( const std::exception &e) {                                    \
         cpputMsg_.addDetail( "Actual  : " +                                  \
                              CPPUNIT_EXTRACT_EXCEPTION_TYPE_( e,             \
                                          "std::exception or derived") );     \
         cpputMsg_.addDetail( std::string("What()  : ") + e.what() );         \
      } catch ( ... ) {                                                       \
         cpputMsg_.addDetail( "Actual  : unknown.");                          \
      }                                                                       \
                                                                              \
      if ( cpputCorrectExceptionThrown_ )                                     \
         break;                                                               \
                                                                              \
      CPPUNIT_NS::Asserter::fail( cpputMsg_,                                  \
                                  CPPUNIT_SOURCELINE() );                     \
   } while ( false )



F>
U>>void CTestGame::TestConstructorBoundaries()
F>

Скромное субъективное мнение: старайтесь в названиях каждого теста описывать утверждения без императива. Чем декларативнее будет название теста, тем качественнее будет ошибка при развале и общее впечатление от кода.
void CGameTestSuite::DimensionsOutsideTheBoundariesAreNotAllowed

название теста не должно отражать что он тестирует, оно должно описывать качество вашей системы. сравните:
"проверить конструктор на граничных условиях" и "запрещено создавать объект вне диапазона размерности"
Ну и старайтесь избегать глобальные переменные типа g_nMaxBoardDim Они делают код нетестируемым (имеется в виду общее качество тестов снижается, к ним меньше доверия ибо тесты не полностью контролируют юнит). Юниты должны быть обособлены от внешнего мира. Всё, что нужно для работы юнита, должно передаваться им на вход.
Успехов.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.