diff --git a/Code/Mantid/Framework/Kernel/test/InterpolationTest.h b/Code/Mantid/Framework/Kernel/test/InterpolationTest.h index ee893140704e..45909fa77a96 100644 --- a/Code/Mantid/Framework/Kernel/test/InterpolationTest.h +++ b/Code/Mantid/Framework/Kernel/test/InterpolationTest.h @@ -10,6 +10,47 @@ using namespace Mantid::Kernel; class InterpolationTest : public CxxTest::TestSuite { public: + /* In the constructor some vectors with values are setup, + * which make the tests easier later on. + * + * To check the interpolated values, call the method + * checkInterpolationResults(const Interpolation &interpolation); + * and supply the interpolation object which is to be tested. The method will call + * further methods to cover all possible edge-cases. On failure, it will be visible + * which case caused the failure. + */ + InterpolationTest() + { + // values for setting up the interpolation + m_tableXValues.push_back(200.0); + m_tableXValues.push_back(201.0); + m_tableXValues.push_back(202.0); + m_tableXValues.push_back(203.0); + m_tableXValues.push_back(204.0); + + m_tableYValues.push_back(50); + m_tableYValues.push_back(60); + m_tableYValues.push_back(100); + m_tableYValues.push_back(300); + m_tableYValues.push_back(400); + + // bulk values for interpolation test + m_interpolationXValues.push_back(200.5); + m_interpolationXValues.push_back(201.25); + m_interpolationXValues.push_back(203.5); + + m_expectedYValues.push_back(55.0); + m_expectedYValues.push_back(70.0); + m_expectedYValues.push_back(350.0); + + // values outside interpolation range + m_outsideXValues.push_back(100.0); + m_outsideXValues.push_back(3000.0); + + m_outsideYValues.push_back(-950.0); + m_outsideYValues.push_back(280000.0); + } + void testCopyConstruction() { Interpolation interpolation; @@ -47,25 +88,29 @@ class InterpolationTest : public CxxTest::TestSuite TS_ASSERT(interpolation.containData() == false); } - void testAddPoint() + void testAddPointOrdered() { Interpolation interpolation; - // insertion order does not matter, interpolation table is always sorted internally - interpolation.addPoint(200.0, 50); - interpolation.addPoint(201.0, 60); - interpolation.addPoint(202.0, 100); - interpolation.addPoint(204.0, 400); - interpolation.addPoint(203.0, 300); + // Add points from values in vectors in correct order. + for(size_t i = 0; i < m_tableXValues.size(); ++i) { + interpolation.addPoint(m_tableXValues[i], m_tableYValues[i]); + } + + // Check correctness of interpolation for different cases + checkInterpolationResults(interpolation); + } + + void testAddPointArbitrary() + { + Interpolation interpolation; - // Test that all the base class member variables are correctly assigned to - TS_ASSERT_DELTA( interpolation.value(100), -950.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(3000), 280000.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(200.5), 55.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(201.25), 70.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(203.5), 350.0 ,0.000000001); + std::vector insertionOrder = {1, 0, 3, 4, 2}; + for(std::vector::const_iterator i = insertionOrder.begin(); i != insertionOrder.end(); ++i) { + interpolation.addPoint(m_tableXValues[*i], m_tableYValues[*i]); + } - TS_ASSERT_EQUALS(interpolation.value(204.0), 400.0); + checkInterpolationResults(interpolation); } void testEmpty() @@ -102,12 +147,7 @@ class InterpolationTest : public CxxTest::TestSuite TS_ASSERT( readIn.getXUnit()->unitID() == xUnit ); TS_ASSERT( readIn.getYUnit()->unitID() == yUnit ); - // Test that all the base class member variables are correctly assigned to - TS_ASSERT_DELTA( readIn.value(100), -950.0 ,0.000000001); - TS_ASSERT_DELTA( readIn.value(3000), 280000.0 ,0.000000001); - TS_ASSERT_DELTA( readIn.value(200.5), 55.0 ,0.000000001); - TS_ASSERT_DELTA( readIn.value(201.25), 70.0 ,0.000000001); - TS_ASSERT_DELTA( readIn.value(203.5), 350.0 ,0.000000001); + checkInterpolationResults(readIn); } void testStreamOperatorsNonEmpty() @@ -120,13 +160,7 @@ class InterpolationTest : public CxxTest::TestSuite // Reconstruct on existing object. str >> interpolation; - TS_ASSERT_DELTA( interpolation.value(100), -950.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(3000), 280000.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(200.5), 55.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(201.25), 70.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(203.5), 350.0 ,0.000000001); - - TS_ASSERT_EQUALS( interpolation.value(201.0), 60.0) + checkInterpolationResults(interpolation); } private: @@ -134,18 +168,78 @@ class InterpolationTest : public CxxTest::TestSuite { Interpolation interpolation; - interpolation.addPoint(200.0, 50); - interpolation.addPoint(201.0, 60); - interpolation.addPoint(202.0, 100); - interpolation.addPoint(203.0, 300); - interpolation.addPoint(204.0, 400); + // take values from constructor + for(size_t i = 0; i < m_tableXValues.size(); ++i) { + interpolation.addPoint(m_tableXValues[i], m_tableYValues[i]); + } interpolation.setXUnit(xUnit); interpolation.setYUnit(yUnit); return interpolation; } + + void checkInterpolationResults(const Interpolation &interpolation) + { + checkValueAtLowerLimit(interpolation); + checkValueAtUpperLimit(interpolation); + checkValuesAtExactBulkPoints(interpolation); + checkValuesInsideInterpolationRange(interpolation); + checkValuesOutsideInterpolationRange(interpolation); + } + + void checkValueAtLowerLimit(const Interpolation &interpolation) + { + checkValue(interpolation, m_tableXValues.front(), m_tableYValues.front(), "at lower limit"); + } + + void checkValueAtUpperLimit(const Interpolation &interpolation) + { + checkValue(interpolation, m_tableXValues.back(), m_tableYValues.back(), "at upper limit"); + } + + void checkValuesAtExactBulkPoints(const Interpolation &interpolation) + { + for(size_t i = 1; i < m_tableXValues.size() - 1; ++i) { + checkValue(interpolation, m_tableXValues[i], m_tableYValues[i], "at interpolation point"); + } + } + + void checkValuesInsideInterpolationRange(const Interpolation &interpolation) { + for(size_t i = 0; i < m_interpolationXValues.size(); ++i) { + checkValue(interpolation, m_interpolationXValues[i], m_expectedYValues[i], "inside interpolation range"); + } + } + + void checkValuesOutsideInterpolationRange(const Interpolation &interpolation) + { + for(size_t i = 0; i < m_outsideXValues.size(); ++i) { + checkValue(interpolation, m_outsideXValues[i], m_outsideYValues[i], "outside interpolation range"); + } + } + + /* This function performs the actual check. + * It takes a string argument to make it more obvious where the problem is. + */ + void checkValue(const Interpolation &interpolation, double x, double y, std::string testedRange) + { + std::ostringstream errorString; + errorString << "Interpolation error " << testedRange; + + TSM_ASSERT_EQUALS(errorString.str().c_str(), interpolation.value(x), y); + } + + // These two vectors contain the data points from which the interpolation is constructed + std::vector m_tableXValues; + std::vector m_tableYValues; + // Two vectors with test values for the "bulk", e.g. no values at the limits and + std::vector m_interpolationXValues; + std::vector m_expectedYValues; + + // Values outside interpolation range + std::vector m_outsideXValues; + std::vector m_outsideYValues; }; #endif /*INTERPOLATIONTEST_H_*/