diff --git a/Core/Code/Common/mitkTestCaller.h b/Core/Code/Common/mitkTestCaller.h index f1bcf9e3bf..f238a76570 100644 --- a/Core/Code/Common/mitkTestCaller.h +++ b/Core/Code/Common/mitkTestCaller.h @@ -1,157 +1,152 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTESTCALLER_H #define MITKTESTCALLER_H #include "cppunit/TestCase.h" #include #include extern std::vector globalCmdLineArgs; namespace mitk { /** * \brief A test caller for parameterized tests. * * This class is not meant to be used directly. Use the * mitk::TestFixture class and MITK_PARAMETERIZED_TEST * instead. */ template class TestCaller : public CppUnit::TestCase { typedef void (ParameterizedFixture::*TestMethod)(); public: /** * Constructor for TestCaller. This constructor builds a new ParameterizedFixture * instance owned by the TestCaller. * \param name name of this TestCaller * \param test the method this TestCaller calls in runTest() */ TestCaller(const std::string& name, TestMethod test) : TestCase(name) , m_OwnFixture(true) , m_Fixture(new ParameterizedFixture()) , m_Test(test) - , m_Parameter(globalCmdLineArgs) { + m_Fixture->m_Parameter = globalCmdLineArgs; } /** * Constructor for TestCaller. * This constructor does not create a new ParameterizedFixture instance but accepts * an existing one as parameter. The TestCaller will not own the * ParameterizedFixture object. * \param name name of this TestCaller * \param test the method this TestCaller calls in runTest() * \param fixture the Fixture to invoke the test method on. */ TestCaller(const std::string& name, TestMethod test, ParameterizedFixture& fixture) : TestCase(name) , m_OwnFixture(false) , m_Fixture(&fixture) , m_Test(test) - , m_Parameter(globalCmdLineArgs) { + m_Fixture->m_Parameter = globalCmdLineArgs; } /** * Constructor for TestCaller. * This constructor does not create a new ParameterizedFixture instance but accepts * an existing one as parameter. The TestCaller will own the * ParameterizedFixture object and delete it in its destructor. * \param name name of this TestCaller * \param test the method this TestCaller calls in runTest() * \param fixture the Fixture to invoke the test method on. */ TestCaller(const std::string& name, TestMethod test, ParameterizedFixture* fixture) : TestCase(name) , m_OwnFixture(true) , m_Fixture(fixture) , m_Test(test) - , m_Parameter(globalCmdLineArgs) { + m_Fixture->m_Parameter = globalCmdLineArgs; } /** * Constructor for TestCaller. * This constructor does not create a new ParameterizedFixture instance but accepts * an existing one as parameter. The TestCaller will own the * ParameterizedFixture object and delete it in its destructor. * \param name name of this TestCaller * \param test the method this TestCaller calls in runTest() * \param fixture the Fixture to invoke the test method on. * \param param A list of string parameters for the fixture. */ TestCaller(const std::string& name, TestMethod test, ParameterizedFixture* fixture, const std::vector& param) : TestCase(name) , m_OwnFixture(true) , m_Fixture(fixture) , m_Test(test) - , m_Parameter(param) { + m_Fixture->m_Parameter = param; } ~TestCaller() { if (m_OwnFixture) delete m_Fixture; } void runTest() { (m_Fixture->*m_Test)(); } void setUp() { - if (!m_Parameter.empty()) - { - m_Fixture->setUpParameter(m_Parameter); - } m_Fixture->setUp(); } void tearDown() { m_Fixture->tearDown(); } std::string toString() const { return "TestCaller " + getName(); } private: TestCaller(const TestCaller& other); TestCaller& operator =(const TestCaller& other); private: bool m_OwnFixture; ParameterizedFixture* m_Fixture; TestMethod m_Test; - std::vector m_Parameter; }; } #endif // MITKTESTCALLER_H diff --git a/Core/Code/Common/mitkTestFixture.h b/Core/Code/Common/mitkTestFixture.h index a3d0af63c5..a15c5fbb7b 100644 --- a/Core/Code/Common/mitkTestFixture.h +++ b/Core/Code/Common/mitkTestFixture.h @@ -1,119 +1,125 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTESTFIXTURE_H #define MITKTESTFIXTURE_H #include #include #include #include #include namespace mitk { /** * \brief Test fixture for parameterized tests * * This class is a drop-in replacement for CppUnit::TextFixture and * enables test methods to access individual parameters. You can also * invoke one method multiple times with different parameters. * * - * The following simple example creates a single test. + * The following simple example creates a single test withoud custom + * parameters: * * \code * class MySimpleTestSuite : public mitk::TestFixture * { * CPPUNIT_TEST_SUITE(MySimpleTestSuite); * MITK_TEST(FivePlusFiveTest); * CPPUNIT_TEST_SUITE_END(); * * public: * void FivePlusFiveTest() * { - * CPPUNIT_ASSERT(5+5=10); + * CPPUNIT_ASSERT(5+5 == 10); * } * }; * MITK_TEST_SUITE_REGISTRATION(MySimpleTestSuite) * \endcode * * * The following example creates a test class containing only * one test method, but the associated test suite contains three tests, * using different parameters for each call of the same method. Use * the macro MITK_PARAMETERIZED_TEST_1 only if you know what you are * doing. If you are not sure, use MITK_TEST instead. * * \code * class MyTestSuite : public mitk::TestFixture * { * CPPUNIT_TEST_SUITE(MyTestSuite); * MITK_PARAMETERIZED_TEST_1(TestSomething, "One"); * MITK_PARAMETERIZED_TEST_1(TestSomething, "Two"); * MITK_PARAMETERIZED_TEST_1(TestSomething, "Three"); * CPPUNIT_TEST_SUITE_END(); * - * private: - * std::string testParam; - * * public: - * void setUpParameter(const std::vector& parameter) - * { - * CPPUNIT_ASSERT(parameter.size() == 1); - * testParam = parameter[0]; - * } * * void TestSomething() * { - * MITK_INFO << "Parameter: " << testParam; + * std::vector parameter = GetTestParameter(); + * CPPUNIT_ASSERT(parameter.size() == 1); + * std::string testParam = parameter[0]; + * + * MITK_INFO << "Parameter: " << testParam; * } * }; * MITK_TEST_SUITE_REGISTRATION(MyTestSuite) * \endcode * * \sa MITK_PARAMETERIZED_TEST * \sa MITK_PARAMETERIZED_TEST_1 */ class TestFixture : public CppUnit::TestFixture { -public: +protected: /** - * \brief Set up parameters for this text fixture + * \brief Get parameters for this test fixture + * + * This method can be called in tests added via the MITK_PARAMETERIZED_TEST + * macro or one of its variants. * - * This method is called for tests added via the MITK_PARAMETERZIED_TEST - * macro or one of its variants. You should override this method and - * set-up the test fixture using the supplied parameters. + * \return The list of \c std::string parameters passed to previous calls + * of the MITK_PARAMETERIZED_TEST macro or one of its variants. * */ - virtual void setUpParameter(const std::vector& parameter) {} - -protected: + std::vector GetTestParameter() const + { + return m_Parameter; + } static std::string getTestDataFilePath(const std::string& testData) { if (itksys::SystemTools::FileIsFullPath(testData.c_str())) return testData; return std::string(MITK_DATA_DIR) + "/" + testData; } + +private: + + template friend class TestCaller; + + std::vector m_Parameter; }; } #endif // MITKTESTFIXTURE_H diff --git a/Core/Code/Testing/mitkDICOMLocaleTest.cpp b/Core/Code/Testing/mitkDICOMLocaleTest.cpp index 246e19fe36..d22bc146aa 100644 --- a/Core/Code/Testing/mitkDICOMLocaleTest.cpp +++ b/Core/Code/Testing/mitkDICOMLocaleTest.cpp @@ -1,142 +1,147 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /* This test is meant to reproduce the following error: - The machine or current user has a German locale. - This esp. means that stream IO expects the decimal separator as a comma: "," - DICOM files use a point "." as the decimal separator to be locale independent - The parser used by MITK (ITK's GDCM) seems to use the current locale instead of the "C" or "POSIX" locale - This leads to spacings (and probably other numbers) being trimmed/rounded, e.g. the correct spacing of 0.314 is read as 1.0 etc. */ #include "mitkDataNodeFactory.h" #include "mitkStandardFileLocations.h" #include "mitkDicomSeriesReader.h" #include "mitkTestingMacros.h" #include "mitkTestFixture.h" #include #include #include class mitkDICOMLocaleTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkDICOMLocaleTestSuite); CPPUNIT_TEST_SUITE_ADD_CUSTOM_TESTS(addDICOMLocaleWithReferenceImageTests); CPPUNIT_TEST_SUITE_END(); private: // A custom method for adding a combination of filename and locale tests static void addDICOMLocaleWithReferenceImageTests(TestSuiteBuilderContextType& context) { std::vector fileArgs; fileArgs.push_back("spacing-ok-ct.dcm"); fileArgs.push_back("spacing-ok-mr.dcm"); fileArgs.push_back("spacing-ok-sc.dcm"); // load a reference DICOM file with German locales being set std::vector localeArgs; localeArgs.push_back("C"); localeArgs.push_back("de_DE"); localeArgs.push_back("de_DE.utf8"); localeArgs.push_back("de_DE.UTF8"); localeArgs.push_back("de_DE@euro"); localeArgs.push_back("German_Germany"); for (std::size_t fileIndex = 0; fileIndex < fileArgs.size(); ++fileIndex) { for (std::size_t localeIndex = 0; localeIndex < localeArgs.size(); ++localeIndex) { MITK_PARAMETERIZED_TEST_2(testLocaleWithReferenceImage, fileArgs[fileIndex], localeArgs[localeIndex]); } } } private: std::string m_FileName; std::string m_Locale; bool m_SkipImageTest; char* m_OldLocale; -public: - - mitkDICOMLocaleTestSuite() : m_OldLocale(NULL) {} - - void setUpParameter(const std::vector ¶meter) + void SetTestParameter() { + std::vector parameter = GetTestParameter(); CPPUNIT_ASSERT(parameter.size() == 2); m_FileName = getTestDataFilePath(parameter[0]); m_Locale = parameter[1]; } +public: + + mitkDICOMLocaleTestSuite() : m_OldLocale(NULL) {} + + + // Change the current locale to m_Locale void setUp() { m_SkipImageTest = false; m_OldLocale = NULL; + SetTestParameter(); + try { m_OldLocale = setlocale(LC_ALL, NULL); MITK_TEST_OUTPUT(<< " ** Changing locale from " << m_OldLocale << " to '" << m_Locale << "'") setlocale(LC_ALL, m_Locale.c_str()); std::cin.imbue(std::locale(m_Locale.c_str())); } catch(...) { MITK_TEST_OUTPUT(<< "Could not activate locale " << m_Locale) m_SkipImageTest = true; } } void tearDown() { if (m_OldLocale) { setlocale(LC_ALL, m_OldLocale); std::cin.imbue(std::locale(m_OldLocale)); } } void testLocaleWithReferenceImage() { if (m_SkipImageTest) return; mitk::Image::Pointer image; mitk::DataNodeFactory::Pointer factory = mitk::DataNodeFactory::New(); factory->SetFileName( m_FileName ); factory->Update(); CPPUNIT_ASSERT(factory->GetNumberOfOutputs() > 0); mitk::DataNode::Pointer node = factory->GetOutput( 0 ); image = dynamic_cast(node->GetData()); CPPUNIT_ASSERT(image.IsNotNull()); // note importance of minor differences in spacings: // DICOM has order y-spacing, x-spacing, while in MITK we assume x-spacing, y-spacing (both meant for 0 and 1 index in array) CPPUNIT_ASSERT_MESSAGE("incorrect x spacing", mitk::Equal(image->GetGeometry()->GetSpacing()[0], 0.3141592)); CPPUNIT_ASSERT_MESSAGE("incorrect y spacing ", mitk::Equal(image->GetGeometry()->GetSpacing()[1], 0.3411592)); } }; MITK_TEST_SUITE_REGISTRATION(mitkDICOMLocale)