Ver código fonte

Merge pull request #645 from jcfr/add-ctk-test-utility

Add ctk test utility
Jean-Christophe Fillion-Robin 9 anos atrás
pai
commit
ee0a82092b

+ 3 - 0
Libs/Core/CMakeLists.txt

@@ -37,6 +37,9 @@ set(KIT_SRCS
   ctkCallback.h
   ctkCommandLineParser.cpp
   ctkCommandLineParser.h
+  ctkCoreTestingUtilities.cpp
+  ctkCoreTestingUtilities.tpp
+  ctkCoreTestingUtilities.h
   ctkDependencyGraph.cpp
   ctkDependencyGraph.h
   ctkErrorLogAbstractMessageHandler.cpp

+ 4 - 0
Libs/Core/Testing/Cpp/CMakeLists.txt

@@ -26,6 +26,8 @@ set(KITTests_SRCS
   ctkBooleanMapperTest.cpp
   ctkCallbackTest1.cpp
   ctkCommandLineParserTest1.cpp
+  ctkCoreTestingMacrosTest.cpp
+  ctkCoreTestingUtilitiesTest.cpp
   ctkExceptionTest.cpp
   ctkFileLoggerTest.cpp
   ctkHighPrecisionTimerTest.cpp
@@ -142,6 +144,8 @@ endif()
 SIMPLE_TEST( ctkBooleanMapperTest )
 SIMPLE_TEST( ctkCallbackTest1 )
 SIMPLE_TEST( ctkCommandLineParserTest1 )
+SIMPLE_TEST( ctkCoreTestingMacrosTest )
+SIMPLE_TEST( ctkCoreTestingUtilitiesTest )
 SIMPLE_TEST( ctkDependencyGraphTest1 )
 SIMPLE_TEST( ctkDependencyGraphTest2 )
 SIMPLE_TEST( ctkExceptionTest )

+ 337 - 0
Libs/Core/Testing/Cpp/ctkCoreTestingMacrosTest.cpp

@@ -0,0 +1,337 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// CTK includes
+#include "ctkCoreTestingMacros.h"
+
+using namespace ctkCoreTestingUtilities;
+
+//----------------------------------------------------------------------------
+int TestCheckNullSuccess();
+int TestCheckNullFailure();
+
+int TestCheckNotNullSuccess();
+int TestCheckNotNullFailure();
+
+int TestCheckExitSuccessSuccess();
+int TestCheckExitSuccessFailure();
+
+int TestCheckIntSuccess();
+int TestCheckIntFailure();
+
+int TestCheckPointerSuccess();
+int TestCheckPointerFailure();
+
+int TestCheckPointerDifferentSuccess();
+int TestCheckPointerDifferentFailure();
+
+int TestCheckBoolSuccess();
+int TestCheckBoolFailure();
+
+int TestCheckStringSuccess();
+int TestCheckStringFailure();
+
+int TestCheckStdStringSuccess();
+int TestCheckStdStringFailure();
+
+int TestCheckQStringSuccess();
+int TestCheckQStringFailure();
+
+int TestCheckStdStringDifferentSuccess();
+int TestCheckStdStringDifferentFailure();
+
+int TestCheckQStringDifferentSuccess();
+int TestCheckQStringDifferentFailure();
+
+//----------------------------------------------------------------------------
+#define TestMacro(MACRO_NAME) \
+  if (Test##MACRO_NAME##Success() != EXIT_SUCCESS) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  if (Test##MACRO_NAME##Failure() != EXIT_FAILURE) \
+    { \
+    return EXIT_FAILURE; \
+    }
+
+//----------------------------------------------------------------------------
+int ctkCoreTestingMacrosTest(int , char * [])
+{
+  TestMacro(CheckNull)
+  TestMacro(CheckNotNull)
+  TestMacro(CheckExitSuccess)
+  TestMacro(CheckInt)
+  TestMacro(CheckPointer)
+  TestMacro(CheckPointerDifferent)
+  TestMacro(CheckBool)
+  TestMacro(CheckString)
+  TestMacro(CheckStdString)
+  TestMacro(CheckQString)
+  TestMacro(CheckStdStringDifferent)
+  TestMacro(CheckQStringDifferent)
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_NULL
+
+//----------------------------------------------------------------------------
+int TestCheckNullSuccess()
+{
+  void * nullPtr = 0;
+  CHECK_NULL(nullPtr);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckNullFailure()
+{
+  int integer = 42;
+  void* notNullPtr = &integer;
+  CHECK_NULL(notNullPtr);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_NOT_NULL
+
+//----------------------------------------------------------------------------
+int TestCheckNotNullSuccess()
+{
+  int integer = 42;
+  void* notNullPtr = &integer;
+  CHECK_NOT_NULL(notNullPtr);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckNotNullFailure()
+{
+  void * nullPtr = 0;
+  CHECK_NOT_NULL(nullPtr);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_EXIT_SUCCESS
+
+//----------------------------------------------------------------------------
+int TestCheckExitSuccessSuccess()
+{
+  int status = EXIT_SUCCESS;
+  CHECK_EXIT_SUCCESS(status);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckExitSuccessFailure()
+{
+  int status = EXIT_FAILURE;
+  CHECK_EXIT_SUCCESS(status);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_INT
+
+//----------------------------------------------------------------------------
+int TestCheckIntSuccess()
+{
+  CHECK_INT(4, 4);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckIntFailure()
+{
+  CHECK_INT(4, 2);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_POINTER
+
+//----------------------------------------------------------------------------
+int TestCheckPointerSuccess()
+{
+  int integer = 42;
+  void* actual = &integer;
+  void* expected = &integer;
+  CHECK_POINTER(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckPointerFailure()
+{
+  int integer = 42;
+  void* actual = &integer;
+  int integer2 = 42;
+  void* expected = &integer2;
+  CHECK_POINTER(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_POINTER_DIFFERENT
+
+//----------------------------------------------------------------------------
+int TestCheckPointerDifferentSuccess()
+{
+  int integer = 42;
+  void* actual = &integer;
+  int integer2 = 42;
+  void* expected = &integer2;
+  CHECK_POINTER_DIFFERENT(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckPointerDifferentFailure()
+{
+  int integer = 42;
+  void* actual = &integer;
+  void* expected = &integer;
+  CHECK_POINTER_DIFFERENT(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_BOOL
+
+//----------------------------------------------------------------------------
+int TestCheckBoolSuccess()
+{
+  CHECK_BOOL(true, true);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckBoolFailure()
+{
+  CHECK_BOOL(true, false);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_STRING
+
+//----------------------------------------------------------------------------
+int TestCheckStringSuccess()
+{
+  const char* actual = "string";
+  const char* expected = "string";
+  CHECK_STRING(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckStringFailure()
+{
+  const char* actual = "string";
+  const char* expected = "string2";
+  CHECK_STRING(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_STD_STRING
+
+//----------------------------------------------------------------------------
+int TestCheckStdStringSuccess()
+{
+  std::string actual = "string";
+  std::string expected = "string";
+  CHECK_STD_STRING(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckStdStringFailure()
+{
+  std::string actual = "string";
+  std::string expected = "string2";
+  CHECK_STD_STRING(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_QSTRING
+
+//----------------------------------------------------------------------------
+int TestCheckQStringSuccess()
+{
+  QString actual = "string";
+  QString expected = "string";
+  CHECK_QSTRING(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckQStringFailure()
+{
+  QString actual = "string";
+  QString expected = "string2";
+  CHECK_QSTRING(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_STD_STRING_DIFFERENT
+
+//----------------------------------------------------------------------------
+int TestCheckStdStringDifferentSuccess()
+{
+  std::string actual = "string";
+  std::string expected = "string2";
+  CHECK_STD_STRING_DIFFERENT(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckStdStringDifferentFailure()
+{
+  std::string actual = "string";
+  std::string expected = "string";
+  CHECK_STD_STRING_DIFFERENT(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+// Test CHECK_QSTRING_DIFFERENT
+
+//----------------------------------------------------------------------------
+int TestCheckQStringDifferentSuccess()
+{
+  QString actual = "string";
+  QString expected = "string2";
+  CHECK_QSTRING_DIFFERENT(actual, expected);
+  return EXIT_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+int TestCheckQStringDifferentFailure()
+{
+  QString actual = "string";
+  QString expected = "string";
+  CHECK_QSTRING_DIFFERENT(actual, expected);
+  return EXIT_SUCCESS;
+}
+

+ 112 - 0
Libs/Core/Testing/Cpp/ctkCoreTestingUtilitiesTest.cpp

@@ -0,0 +1,112 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// CTK includes
+#include "ctkCoreTestingUtilities.h"
+
+using namespace ctkCoreTestingUtilities;
+
+//----------------------------------------------------------------------------
+bool TestCheckInt();
+bool TestCheckNotNull();
+bool TestCheckNull();
+bool TestCheckPointer();
+bool TestCheckString();
+
+//----------------------------------------------------------------------------
+int ctkCoreTestingUtilitiesTest(int , char * [])
+{
+  bool res = true;
+  res = res && TestCheckInt();
+  res = res && TestCheckNotNull();
+  res = res && TestCheckNull();
+  res = res && TestCheckPointer();
+  res = res && TestCheckString();
+  return res ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+//----------------------------------------------------------------------------
+bool TestCheckInt()
+{
+  if (!CheckInt(__LINE__, "TestCheckInt", 1, 1)
+      || CheckInt(__LINE__, "TestCheckInt Expected Failure", 1, -1))
+    {
+    qWarning() << "Line " << __LINE__ << " - TestCheckInt failed";
+    return false;
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool TestCheckNotNull()
+{
+  int foo = 1;
+  if (!CheckNotNull(__LINE__, "TestCheckNotNull", &foo)
+      || CheckNotNull(__LINE__, "TestCheckNotNull Expected Failure", 0))
+    {
+    qWarning() << "Line " << __LINE__ << " - TestCheckNotNull failed";
+    return false;
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool TestCheckNull()
+{
+  int foo = 1;
+  if (!CheckNull(__LINE__, "TestCheckNull", 0)
+      || CheckNull(__LINE__, "TestCheckNull Expected Failure", &foo))
+    {
+    qWarning() << "Line " << __LINE__ << " - TestCheckNull failed";
+    return false;
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool TestCheckPointer()
+{
+  int foo = 1;
+  int bar = 1;
+  if (!CheckPointer(__LINE__, "TestCheckPointer", &foo, &foo)
+      || CheckPointer(__LINE__, "TestCheckPointer Expected Failure", &foo, &bar))
+    {
+    qWarning() << "Line " << __LINE__ << " - TestCheckPointer failed";
+    return false;
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool TestCheckString()
+{
+  const char* foo = "foo";
+  const char* bar = "bar";
+  if (!CheckString(__LINE__, "TestCheckString", 0, 0)
+      ||!CheckString(__LINE__, "TestCheckString", foo, foo)
+      || CheckString(__LINE__, "TestCheckString Expected Failure", foo, bar)
+      || CheckString(__LINE__, "TestCheckString Expected Failure", foo, 0))
+    {
+    qWarning() << "Line " << __LINE__ << " - TestCheckString failed";
+    return false;
+    }
+  return true;
+}
+

+ 187 - 0
Libs/Core/ctkCoreTestingMacros.h

@@ -0,0 +1,187 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkCoreTestingMacros_h
+#define __ctkCoreTestingMacros_h
+
+#include "ctkCoreTestingUtilities.h"
+
+/// Convenience macros for unit tests.
+///
+/// The macro returns from the current method with EXIT_FAILURE if the check fails.
+/// Expressions can be passed as arguments, they are guaranteed to be executed only once.
+///
+/// Example:
+///
+/// \code{.cpp}
+/// int testedFunction(int a, int b) { return a+b; }
+///
+/// int MyTest1(int , char * [])
+/// {
+///
+///   int current = 40 + 2;
+///   int expected = 42;
+///   CHECK_INT(current, expected);
+///
+///   CHECK_INT(testedFunction(40,2), 42);
+///   CHECK_INT(testedFunction(35,5), 40);
+///
+///   return EXIT_SUCCESS;
+/// }
+///
+/// \endcode
+
+/// Verifies that pointer is NULL
+#define CHECK_NULL(pointer) \
+  { \
+  const void* pointerValue = (pointer); \
+  if (!ctkCoreTestingUtilities::CheckNull(__LINE__,#pointer " is not NULL", pointerValue)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies that pointer is not NULL
+#define CHECK_NOT_NULL(pointer) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckNotNull(__LINE__,#pointer " is NULL", (pointer))) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+#define CHECK_EXIT_SUCCESS(actual) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckInt(__LINE__,#actual " != EXIT_SUCCESS", (actual), EXIT_SUCCESS)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual int value is the same as expected
+#define CHECK_INT(actual, expected) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckInt(__LINE__,#actual " != " #expected, (actual), (expected))) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual pointer value is the same as expected
+#define CHECK_POINTER(actual, expected) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckPointer(__LINE__,#actual " != " #expected, (actual), (expected))) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual pointer value is the same as expected
+#define CHECK_POINTER_DIFFERENT(actual, expected) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckPointer(__LINE__,#actual " == " #expected, (actual), (expected), false)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual bool value is the same as expected
+#define CHECK_BOOL(actual, expected) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckInt(__LINE__,#actual " != " #expected, (actual)?1:0, (expected)?1:0)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual const char* value is the same as expected.
+/// It can handle NULL pointer inputs.
+#define CHECK_STRING(actual, expected) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckString(__LINE__,#actual " != " #expected, (actual), (expected))) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual std::string value is the same as expected.
+/// It is safe to use for comparing std::string values.
+/// It cannot handle NULL pointer inputs.
+#define CHECK_STD_STRING(actual, expected) \
+  { \
+  std::string a = (actual); \
+  std::string e = (expected); \
+  if (!ctkCoreTestingUtilities::CheckString(__LINE__,#actual " != " #expected, a.c_str(), e.c_str())) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual QString value is the same as expected.
+/// It is safe to use for comparing QString values.
+/// It cannot handle NULL pointer inputs.
+#define CHECK_QSTRING(actual, expected) \
+  { \
+  QString a = (actual); \
+  QString e = (expected); \
+  if (!ctkCoreTestingUtilities::CheckString(__LINE__,#actual " != " #expected, qPrintable(a), qPrintable(e))) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual const char* value is not the same as expected.
+/// It can handle NULL pointer inputs.
+#define CHECK_STRING_DIFFERENT(actual, expected) \
+  { \
+  if (!ctkCoreTestingUtilities::CheckString(__LINE__,#actual " != " #expected, (actual), (expected), false)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual std::string value is not the same as expected.
+/// It is safe to use for comparing std::string values.
+/// It cannot handle NULL pointer inputs.
+#define CHECK_STD_STRING_DIFFERENT(actual, expected) \
+  { \
+  std::string a = (actual); \
+  std::string e = (expected); \
+  if (!ctkCoreTestingUtilities::CheckString(__LINE__,#actual " != " #expected, a.c_str(), e.c_str(), false)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+/// Verifies if actual QString value is not the same as expected.
+/// It is safe to use for comparing QString values.
+/// It cannot handle NULL pointer inputs.
+#define CHECK_QSTRING_DIFFERENT(actual, expected) \
+  { \
+  QString a = (actual); \
+  QString e = (expected); \
+  if (!ctkCoreTestingUtilities::CheckString(__LINE__,#actual " != " #expected, qPrintable(a), qPrintable(e), false)) \
+    { \
+    return EXIT_FAILURE; \
+    } \
+  }
+
+#endif
+

+ 75 - 0
Libs/Core/ctkCoreTestingUtilities.cpp

@@ -0,0 +1,75 @@
+
+#include "ctkCoreTestingUtilities.h"
+
+namespace ctkCoreTestingUtilities
+{
+
+//----------------------------------------------------------------------------
+bool CheckInt(int line, const QString& description,
+              int current, int expected)
+{
+  return Check<int>(line, description, current, expected, "CheckInt");
+}
+
+//----------------------------------------------------------------------------
+bool CheckNotNull(int line, const QString& description,
+                  const void* pointer)
+{
+  if(!pointer)
+    {
+    qWarning() << "\nLine " << line << " - " << description
+               << " : CheckNotNull failed"
+               << "\n\tpointer:" << pointer;
+    return false;
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool CheckNull(int line, const QString& description, const void* pointer)
+{
+  if(pointer)
+    {
+    qWarning() << "\nLine " << line << " - " << description
+               << " : CheckNull failed"
+               << "\n\tpointer:" << pointer;
+    return false;
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool CheckPointer(int line, const QString& description,
+                  void* current, void* expected, bool errorIfDifferent /* = true */)
+{
+  return Check<void*>(line, description, current, expected, "CheckPointer", errorIfDifferent);
+}
+
+//----------------------------------------------------------------------------
+bool CheckString(int line, const QString& description,
+                 const char* current, const char* expected, bool errorIfDifferent /* = true */)
+{
+  QString testName = "CheckString";
+
+  bool different = true;
+  if (current == 0 || expected == 0)
+    {
+    different = !(current == 0 && expected == 0);
+    }
+  else if(strcmp(current, expected) == 0)
+    {
+    different = false;
+    }
+  if(different == errorIfDifferent)
+    {
+    qWarning() << "\nLine " << line << " - " << description
+               << " : " << testName << "  failed"
+               << "\n\tcurrent :" << (current ? current : "<null>")
+               << "\n\texpected:" << (expected ? expected : "<null>");
+    return false;
+    }
+  return true;
+}
+
+} // namespace ctkCoreTestingUtilities
+

+ 76 - 0
Libs/Core/ctkCoreTestingUtilities.h

@@ -0,0 +1,76 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkCoreTestingUtilities_h
+#define __ctkCoreTestingUtilities_h
+
+// CTK includes
+#include <ctkCoreExport.h>
+
+// Qt includes
+#include <QString>
+
+/// This module provides functions to facilitate writing tests.
+///
+/// Before using this module, first consider the QTestLib
+/// unit testing framework available in Qt.
+///
+/// Example:
+///
+/// \code{.cpp}
+/// int current = 40 + 2;
+/// int expected = 43;
+/// if (!CheckInt(__LINE__, "40 + 2", current, expected))
+///   {
+///   return false;
+///   }
+/// \endcode
+///
+/// Usually these test methods are used by single-line convenience macros
+/// defined in ctkCoreTestingMacros.h.
+
+namespace ctkCoreTestingUtilities
+{
+
+CTK_CORE_EXPORT
+bool CheckInt(int line, const QString& description,
+              int current, int expected);
+
+CTK_CORE_EXPORT
+bool CheckNotNull(int line, const QString& description,
+                  const void* pointer);
+
+CTK_CORE_EXPORT
+bool CheckNull(int line, const QString& description,
+               const void* pointer);
+
+CTK_CORE_EXPORT
+bool CheckPointer(int line, const QString& description,
+                  void* current, void* expected, bool errorIfDifferent = true);
+
+CTK_CORE_EXPORT
+bool CheckString(int line, const QString& description,
+                 const char* current, const char* expected, bool errorIfDifferent = true );
+
+} // namespace ctkCoreTestingUtilities
+
+#include "ctkCoreTestingUtilities.tpp"
+
+#endif

+ 61 - 0
Libs/Core/ctkCoreTestingUtilities.tpp

@@ -0,0 +1,61 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+
+namespace ctkCoreTestingUtilities
+{
+
+//----------------------------------------------------------------------------
+template<typename TYPE>
+bool Check(int line, const QString& description,
+           TYPE current, TYPE expected,
+           const QString& _testName,
+           bool errorIfDifferent = true)
+{
+  QString testName = _testName.isEmpty() ? "Check" : _testName;
+  if (errorIfDifferent)
+    {
+    if(current != expected)
+      {
+      qWarning() << "\nLine " << line << " - " << description
+                 << " : " << testName << " failed"
+                 << "\n\tcurrent :" << current
+                 << "\n\texpected:" << expected;
+      return false;
+      }
+    }
+  else
+    {
+    if(current == expected)
+      {
+      qWarning() << "\nLine " << line << " - " << description
+                 << " : " << testName << " failed"
+                 << "\n\tcurrent :" << current
+                 << "\n\texpected to be different from:" << expected;
+      return false;
+      }
+    }
+  return true;
+}
+
+} // namespace ctkCoreTestingUtilities
+

+ 55 - 163
Libs/Widgets/Testing/Cpp/ctkSettingsPanelTest1.cpp

@@ -28,6 +28,7 @@
 
 // CTK includes
 #include "ctkBooleanMapper.h"
+#include "ctkCoreTestingMacros.h"
 #include "ctkSettingsPanel.h"
 
 // STD includes
@@ -67,6 +68,9 @@ int ctkSettingsPanelTest1(int argc, char * argv [] )
   ctkSettingsPanelForTest settingsPanel;
   settingsPanel.setSettings(&settings);
 
+  //
+  // QCheckBox
+  //
   QCheckBox* box = new QCheckBox(&settingsPanel);
 
   settingsPanel.registerProperty("key 1", box, "checked",
@@ -74,170 +78,79 @@ int ctkSettingsPanelTest1(int argc, char * argv [] )
   
   // Check settings value after a property is registered
   QVariant boxVal = settings.value("key 1");
-  if (!boxVal.isValid() || boxVal.toBool() != false)
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 1").toBool() != false)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 1").toBool() != false)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(boxVal.isValid(), true);
+  CHECK_BOOL(boxVal.toBool(), false);
+  CHECK_BOOL(settingsPanel.myPreviousPropertyValue("key 1").toBool(), false);
+  CHECK_BOOL(settingsPanel.myPropertyValue("key 1").toBool(), false);
+
   // Update value using the object/widget API
   box->setChecked(true);
 
   // Check settings value after it has been updated using object/widget API
   boxVal = settings.value("key 1");
-  if (!boxVal.isValid() || boxVal.toBool() != true)
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 1").toBool() != false)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 1").toBool() != true)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-
-
+  CHECK_BOOL(boxVal.isValid(), true);
+  CHECK_BOOL(boxVal.toBool(), true);
+  CHECK_BOOL(settingsPanel.myPreviousPropertyValue("key 1").toBool(), false);
+  CHECK_BOOL(settingsPanel.myPropertyValue("key 1").toBool(), true);
+
+  //
+  // QLineEdit
+  //
   QLineEdit* lineEdit = new QLineEdit("default", &settingsPanel);
   settingsPanel.registerProperty("key 2", lineEdit, "text",
                                   SIGNAL(textChanged(QString)));
 
   // Check value after a property is registered
   QVariant lineEditVal = settings.value("key 2");
-  if (!lineEditVal.isValid() || lineEditVal.toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myDefaultPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(lineEditVal.isValid(), true);
+  CHECK_QSTRING(lineEditVal.toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myPreviousPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myDefaultPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myPropertyValue("key 2").toString(), QString("default"));
 
   // Update value using the object/widget API
   lineEdit->setText("first edit");
 
   // Check settings value after it has been updated using object/widget API
   lineEditVal = settings.value("key 2");
-  if (!lineEditVal.isValid() || lineEditVal.toString() != "first edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myDefaultPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 2").toString() != "first edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(lineEditVal.isValid(), true);
+  CHECK_QSTRING(lineEditVal.toString(), QString("first edit"));
+  CHECK_QSTRING(settingsPanel.myPreviousPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myDefaultPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myPropertyValue("key 2").toString(), QString("first edit"));
 
   // Check settings value after applySettings() has been called
   settingsPanel.applySettings();
   lineEditVal = settings.value("key 2");
-  if (!lineEditVal.isValid() || lineEditVal.toString() != "first edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 2").toString() != "first edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myDefaultPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 2").toString() != "first edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(lineEditVal.isValid(), true);
+  CHECK_QSTRING(lineEditVal.toString(), QString("first edit"));
+  CHECK_QSTRING(settingsPanel.myPreviousPropertyValue("key 2").toString(), QString("first edit"));
+  CHECK_QSTRING(settingsPanel.myDefaultPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myPropertyValue("key 2").toString(), QString("first edit"));
 
   // Update value using the object/widget API
   lineEdit->setText("second edit");
 
   // Check settings value after it has been updated using object/widget API
   lineEditVal = settings.value("key 2");
-  if (!lineEditVal.isValid() || lineEditVal.toString() != "second edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 2").toString() != "first edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myDefaultPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 2").toString() != "second edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(lineEditVal.isValid(), true);
+  CHECK_QSTRING(lineEditVal.toString(), QString("second edit"));
+  CHECK_QSTRING(settingsPanel.myPreviousPropertyValue("key 2").toString(), QString("first edit"));
+  CHECK_QSTRING(settingsPanel.myDefaultPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myPropertyValue("key 2").toString(), QString("second edit"));
 
   // Check settings value after applySettings() has been called
   settingsPanel.applySettings();
   lineEditVal = settings.value("key 2");
-  if (!lineEditVal.isValid() || lineEditVal.toString() != "second edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key 2").toString() != "second edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myDefaultPropertyValue("key 2").toString() != "default")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key 2").toString() != "second edit")
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-
+  CHECK_BOOL(lineEditVal.isValid(), true);
+  CHECK_QSTRING(lineEditVal.toString(), QString("second edit"));
+  CHECK_QSTRING(settingsPanel.myPreviousPropertyValue("key 2").toString(), QString("second edit"));
+  CHECK_QSTRING(settingsPanel.myDefaultPropertyValue("key 2").toString(), QString("default"));
+  CHECK_QSTRING(settingsPanel.myPropertyValue("key 2").toString(), QString("second edit"));
+
+  //
+  // QCheckBox + ctkBooleanMapper
+  //
   box->setChecked(false);
   settingsPanel.registerProperty("key complement",
                                  new ctkBooleanMapper(box, "checked", SIGNAL(toggled(bool))),
@@ -246,41 +159,20 @@ int ctkSettingsPanelTest1(int argc, char * argv [] )
 
   // Check settings value after a property is registered
   boxVal = settings.value("key complement");
-  if (!boxVal.isValid() || boxVal.toBool() != true)
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key complement").toBool() != true)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key complement").toBool() != true)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(boxVal.isValid(), true);
+  CHECK_BOOL(boxVal.toBool(), true);
+  CHECK_BOOL(settingsPanel.myPreviousPropertyValue("key complement").toBool(), true);
+  CHECK_BOOL(settingsPanel.myPropertyValue("key complement").toBool(), true);
+
   // Update value using the object/widget API
   box->setChecked(true);
 
   // Check settings value after it has been updated using object/widget API
   boxVal = settings.value("key complement");
-  if (!boxVal.isValid() || boxVal.toBool() != false)
-    {
-    std::cerr << "Line " << __LINE__ << " - Saving to settings failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPreviousPropertyValue("key complement").toBool() != true)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with previousPropertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (settingsPanel.myPropertyValue("key complement").toBool() != false)
-    {
-    std::cerr << "Line " << __LINE__ << " - Problem with propertyValue()!" << std::endl;
-    return EXIT_FAILURE;
-    }
+  CHECK_BOOL(boxVal.isValid(), true);
+  CHECK_BOOL(boxVal.toBool(), false);
+  CHECK_BOOL(settingsPanel.myPreviousPropertyValue("key complement").toBool(), true);
+  CHECK_BOOL(settingsPanel.myPropertyValue("key complement").toBool(), false);
 
   settingsPanel.show();