I've just finished the relative error patch, I of course added all the tests
as well. This is a new feature and doesn't touch and of the existing
functions, so it should be an easy addition. It does however, require cmath
for the fabs function, if this is a problem and someone can offer a non
library dependent absolute value function I'd be happy to replace fabs. VC++
has a fabs funcion but I'm not sure about the includes nessecary for it,
etc. It also treats comparisons with zero as a special case, to avoid
division by zero it calls AreClose for (expected==0.0).
The interface is as follows:
For all instances of the *CLOSE macro or *Close function the word RELATIVELY
or Relatively have been appended.
Example
CHECK_RELATIVELY_CLOSE(1.0f,1.01f,0.01f)
On Thu, Feb 4, 2010 at 4:36 PM, Sean Farrell <sean.farr...@rioki.org> wrote:
> Hi looks interesting.
>
> Since it is very small and portable, care to make a patch?
>
> Sean
>
> On Thu, Feb 4, 2010 at 9:18 PM, Charles Mark Maynard <cmayn...@gmail.com>
> wrote:
> > Hello all, I have been using UnitTest++ and am currently working on a
> > project and researching 3 numerical libraries(TET,GSL,BOOST MATH). While
> > testing I've ran into a problem using CHECK_ARRAY_CLOSE. It is not a bug,
> > but rather that in some cases the numbers are so large that is would be
> > better to check relative error then absolute. I would like to propose a
> new
> > comparison test CHECK_ARRAY_RELATIVE, which would use relative error
> instead
> > for values larger than the tolerance value.
> >
> > Currently I have resorted to using the following conditional to check
> > absolute or relatvie based on the size of the values I'm comparing:
> >
> > bool pass=true;
> > //choose between checking relative or absolute error
> > if(fabs(pnm.TET_pnm_r()[j])<accuracy ||
> fabs(pnm.GSL_pnm_r()[j])<accuracy)
> > {
> > //absolute error
> > if(fabs(pnm.TET_pnm_r()[j]-pnm.GSL_pnm_r()[j])<accuracy)
> > std::cout<<"Absolute N: "<<n<<" M: "<<m<<" TET:
> "<<pnm.TET_pnm_r()[j]<<"
> > GSL: " << pnm.GSL_pnm_r()[j]<<" RIGHT\n";
> > else
> > {
> > std::cout<<"***** Absolute N: "<<n<<" M: "<<m<<" TET:
> > "<<pnm.TET_pnm_r()[j]<<" GSL: " << pnm.GSL_pnm_r()[j]<<" WRONG\n";
> > pass=false;
> > }
> > }
> > else
> > {
> > //relative error
> >
> >
> if((fabs(pnm.TET_pnm_r()[j]-pnm.GSL_pnm_r()[j])/pnm.TET_pnm_r()[j])<accuracy)
> > std::cout<<"Relative N: "<<n<<" M: "<<m<<" TET:
> "<<pnm.TET_pnm_r()[j]<<"
> > GSL: " << pnm.GSL_pnm_r()[j]<<" RIGHT\n";
> > else
> > {
> > std::cout<<"***** Relative N: "<<n<<" M: "<<m<<" TET:
> > "<<pnm.TET_pnm_r()[j]<<" GSL: " << pnm.GSL_pnm_r()[j]<<" WRONG\n";
> > pass=false;
> > }
> > }
> >
> > Let me know if this is of interest, I would be willing to help with
> > development. I've looked at through the repository, and this shouldn't
> take
> > too much effort to add, mostly a new AreRelativelyClose method and a less
> > than comparison of the expected term with the tolerance to decide which
> one
> > to call.
> >
> > Cheers,
> > Mark
> >
> >
> ------------------------------------------------------------------------------
> > The Planet: dedicated and managed hosting, cloud storage, colocation
> > Stay online with enterprise data centers and the best network in the
> > business
> > Choose flexible plans and management services without long-term contracts
> > Personal 24x7 support from experience hosting pros just a phone call
> away.
> > http://p.sf.net/sfu/theplanet-com
> > _______________________________________________
> > unittest-cpp-devel mailing list
> > unittest-cpp-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/unittest-cpp-devel
> >
> >
>
>
> ------------------------------------------------------------------------------
> The Planet: dedicated and managed hosting, cloud storage, colocation
> Stay online with enterprise data centers and the best network in the
> business
> Choose flexible plans and management services without long-term contracts
> Personal 24x7 support from experience hosting pros just a phone call away.
> http://p.sf.net/sfu/theplanet-com
> _______________________________________________
> unittest-cpp-devel mailing list
> unittest-cpp-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/unittest-cpp-devel
>
Index: src/Checks.h
===================================================================
--- src/Checks.h (revision 207)
+++ src/Checks.h (working copy)
@@ -1,6 +1,7 @@
#ifndef UNITTEST_CHECKS_H
#define UNITTEST_CHECKS_H
+#include <cmath>
#include "Config.h"
#include "TestResults.h"
#include "MemoryOutStream.h"
@@ -42,6 +43,15 @@
}
template< typename Expected, typename Actual, typename Tolerance >
+bool AreRelativelyClose(Expected const& expected, Actual const& actual, Tolerance const& tolerance)
+{
+ if(actual!=0.0)
+ return ((fabs(actual - expected) / actual) <= tolerance);
+ else
+ return AreClose(expected, actual, tolerance);
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
void CheckClose(TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance,
TestDetails const& details)
{
@@ -54,7 +64,19 @@
}
}
+template< typename Expected, typename Actual, typename Tolerance >
+void CheckRelativelyClose(TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance,
+ TestDetails const& details)
+{
+ if (!AreRelativelyClose(expected, actual, tolerance))
+ {
+ UnitTest::MemoryOutStream stream;
+ stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual;
+ results.OnTestFailure(details, stream.GetText());
+ }
+}
+
template< typename Expected, typename Actual >
void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual,
int const count, TestDetails const& details)
@@ -93,6 +115,15 @@
}
template< typename Expected, typename Actual, typename Tolerance >
+bool ArrayAreRelativelyClose(Expected const& expected, Actual const& actual, int const count, Tolerance const& tolerance)
+{
+ bool equal = true;
+ for (int i = 0; i < count; ++i)
+ equal &= AreRelativelyClose(expected[i], actual[i], tolerance);
+ return equal;
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
void CheckArrayClose(TestResults& results, Expected const& expected, Actual const& actual,
int const count, Tolerance const& tolerance, TestDetails const& details)
{
@@ -116,6 +147,29 @@
}
template< typename Expected, typename Actual, typename Tolerance >
+void CheckArrayRelativelyClose(TestResults& results, Expected const& expected, Actual const& actual,
+ int const count, Tolerance const& tolerance, TestDetails const& details)
+{
+ bool equal = ArrayAreRelativelyClose(expected, actual, count, tolerance);
+
+ if (!equal)
+ {
+ UnitTest::MemoryOutStream stream;
+
+ stream << "Expected [ ";
+ for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex)
+ stream << expected[expectedIndex] << " ";
+ stream << "] +/- " << tolerance << " but was [ ";
+
+ for (int actualIndex = 0; actualIndex < count; ++actualIndex)
+ stream << actual[actualIndex] << " ";
+ stream << "]";
+
+ results.OnTestFailure(details, stream.GetText());
+ }
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
void CheckArray2DClose(TestResults& results, Expected const& expected, Actual const& actual,
int const rows, int const columns, Tolerance const& tolerance, TestDetails const& details)
{
@@ -153,6 +207,44 @@
}
}
+template< typename Expected, typename Actual, typename Tolerance >
+void CheckArray2DRelativelyClose(TestResults& results, Expected const& expected, Actual const& actual,
+ int const rows, int const columns, Tolerance const& tolerance, TestDetails const& details)
+{
+ bool equal = true;
+ for (int i = 0; i < rows; ++i)
+ equal &= ArrayAreRelativelyClose(expected[i], actual[i], columns, tolerance);
+
+ if (!equal)
+ {
+ UnitTest::MemoryOutStream stream;
+
+ stream << "Expected [ ";
+
+ for (int expectedRow = 0; expectedRow < rows; ++expectedRow)
+ {
+ stream << "[ ";
+ for (int expectedColumn = 0; expectedColumn < columns; ++expectedColumn)
+ stream << expected[expectedRow][expectedColumn] << " ";
+ stream << "] ";
+ }
+
+ stream << "] +/- " << tolerance << " but was [ ";
+
+ for (int actualRow = 0; actualRow < rows; ++actualRow)
+ {
+ stream << "[ ";
+ for (int actualColumn = 0; actualColumn < columns; ++actualColumn)
+ stream << actual[actualRow][actualColumn] << " ";
+ stream << "] ";
+ }
+
+ stream << "]";
+
+ results.OnTestFailure(details, stream.GetText());
+ }
}
+}
+
#endif
Index: src/tests/TestChecks.cpp
===================================================================
--- src/tests/TestChecks.cpp (revision 207)
+++ src/tests/TestChecks.cpp (working copy)
@@ -180,7 +180,90 @@
CHECK_EQUAL(10, reporter.lastFailedLine);
}
+TEST(CheckRelativelyCloseTrue)
+{
+ TestResults results;
+ CheckRelativelyClose(results, 3.001f, 3.0f, 0.1f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(0, results.GetFailureCount());
+}
+TEST(CheckRelativelyCloseFalse)
+{
+ TestResults results;
+ CheckRelativelyClose(results, 3.5f, 3.0f, 0.1f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckRelativelyCloseWithZeroEpsilonWorksForSameNumber)
+{
+ TestResults results;
+ CheckRelativelyClose(results, 0.1f, 0.1f, 0, TestDetails("", "", "", 0));
+ CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckRelativelyCloseWithNaNFails)
+{
+ union
+ {
+ unsigned int bitpattern;
+ float nan;
+ };
+ bitpattern = 0xFFFFFFFF;
+ TestResults results;
+ CheckRelativelyClose(results, 3.0f, nan, 0.1f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckRelativelyCloseWithNaNAgainstItselfFails)
+{
+ union
+ {
+ unsigned int bitpattern;
+ float nan;
+ };
+ bitpattern = 0xFFFFFFFF;
+ TestResults results;
+ CheckRelativelyClose(results, nan, nan, 0.1f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckRelativelyCloseFailureIncludesCheckExpectedAndActual)
+{
+ RecordingReporter reporter;
+ TestResults results(&reporter);
+ const float expected = 0.9f;
+ const float actual = 1.1f;
+ CheckRelativelyClose(results, expected, actual, 0.01f, TestDetails("", "", "", 0));
+
+ using namespace std;
+ CHECK(strstr(reporter.lastFailedMessage, "xpected 0.9"));
+ CHECK(strstr(reporter.lastFailedMessage, "was 1.1"));
+}
+
+TEST(CheckRelativelyCloseFailureIncludesTolerance)
+{
+ RecordingReporter reporter;
+ TestResults results(&reporter);
+ CheckRelativelyClose(results, 2, 3, 0.01f, TestDetails("", "", "", 0));
+
+ using namespace std;
+ CHECK(strstr(reporter.lastFailedMessage, "0.01"));
+}
+
+TEST(CheckRelativelyCloseFailureIncludesDetails)
+{
+ RecordingReporter reporter;
+ TestResults results(&reporter);
+ TestDetails const details("mytest", "mysuite", "header.h", 10);
+
+ CheckRelativelyClose(results, 2, 3, 0.01f, details);
+
+ CHECK_EQUAL("mytest", reporter.lastFailedTest);
+ CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("header.h", reporter.lastFailedFile);
+ CHECK_EQUAL(10, reporter.lastFailedLine);
+}
+
TEST(CheckArrayEqualTrue)
{
TestResults results;
@@ -236,7 +319,42 @@
CHECK_EQUAL(1337, reporter.lastFailedLine);
}
+TEST(CheckArrayRelativelyCloseTrue)
+{
+ TestResults results;
+ float const array1[3] = { 1.0f, 1.5f, 2.0f };
+ float const array2[3] = { 1.01f, 1.51f, 2.01f };
+ CheckArrayRelativelyClose(results, array1, array2, 3, 0.02f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckArrayRelativelyCloseFalse)
+{
+ TestResults results;
+
+ float const array1[3] = { 1.0f, 1.5f, 2.0f };
+ float const array2[3] = { 1.01f, 1.51f, 2.01f };
+ CheckArrayRelativelyClose(results, array1, array2, 3, 0.001f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckArrayRelativelyCloseFailureIncludesDetails)
+{
+ RecordingReporter reporter;
+ TestResults results(&reporter);
+ TestDetails const details("arrayRelativelyCloseTest", "arrayRelativelyCloseSuite", "file", 1337);
+
+ float const array1[3] = { 1.0f, 1.5f, 2.0f };
+ float const array2[3] = { 1.01f, 1.51f, 2.01f };
+ CheckArrayClose(results, array1, array2, 3, 0.001f, details);
+
+ CHECK_EQUAL("arrayRelativelyCloseTest", reporter.lastFailedTest);
+ CHECK_EQUAL("arrayRelativelyCloseSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("file", reporter.lastFailedFile);
+ CHECK_EQUAL(1337, reporter.lastFailedLine);
+}
+
TEST(CheckArray2DCloseTrue)
{
TestResults results;
@@ -265,11 +383,44 @@
CHECK_EQUAL(1, results.GetFailureCount());
}
+TEST(CheckArray2DRelativelyCloseTrue)
+{
+ TestResults results;
+
+ float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
+ { 2.0f, 2.5f, 3.0f },
+ { 3.0f, 3.5f, 4.0f } };
+ float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
+ { 2.01f, 2.51f, 3.01f },
+ { 3.01f, 3.51f, 4.01f } };
+ CheckArray2DRelativelyClose(results, array1, array2, 3, 3, 0.02f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckArray2DRelativelyCloseFalse)
+{
+ TestResults results;
+
+ float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
+ { 2.0f, 2.5f, 3.0f },
+ { 3.0f, 3.5f, 4.0f } };
+ float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
+ { 2.01f, 2.51f, 3.01f },
+ { 3.01f, 3.51f, 4.01f } };
+ CheckArray2DRelativelyClose(results, array1, array2, 3, 3, 0.001f, TestDetails("", "", "", 0));
+ CHECK_EQUAL(1, results.GetFailureCount());
+}
+
TEST(CheckCloseWithDoublesSucceeds)
{
CHECK_CLOSE(0.5, 0.5, 0.0001);
}
+TEST(CheckRelativelyCloseWithDoublesSucceeds)
+{
+ CHECK_RELATIVELY_CLOSE(0.5, 0.5, 0.0001);
+}
+
TEST(CheckArray2DCloseFailureIncludesDetails)
{
RecordingReporter reporter;
@@ -290,4 +441,24 @@
CHECK_EQUAL(1234, reporter.lastFailedLine);
}
+TEST(CheckArray2DRelativelyCloseFailureIncludesDetails)
+{
+ RecordingReporter reporter;
+ TestResults results(&reporter);
+ TestDetails const details("array2DRelativelyCloseTest", "array2DRelativelyCloseSuite", "file", 1234);
+
+ float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
+ { 2.0f, 2.5f, 3.0f },
+ { 3.0f, 3.5f, 4.0f } };
+ float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
+ { 2.01f, 2.51f, 3.01f },
+ { 3.01f, 3.51f, 4.01f } };
+ CheckArray2DRelativelyClose(results, array1, array2, 3, 3, 0.001f, details);
+
+ CHECK_EQUAL("array2DRelativelyCloseTest", reporter.lastFailedTest);
+ CHECK_EQUAL("array2DRelativelyCloseSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("file", reporter.lastFailedFile);
+ CHECK_EQUAL(1234, reporter.lastFailedLine);
}
+
+}
Index: src/tests/TestCheckMacros.cpp
===================================================================
--- src/tests/TestCheckMacros.cpp (revision 207)
+++ src/tests/TestCheckMacros.cpp (working copy)
@@ -326,7 +326,118 @@
CHECK_EQUAL(1, g_sideEffect);
}
+TEST(CheckRelativelyCloseSucceedsOnEqual)
+{
+ bool failure = true;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+ CHECK_RELATIVELY_CLOSE (1.0f, 1.001f, 0.01f);
+ failure = (testResults.GetFailureCount() > 0);
+ }
+ CHECK(!failure);
+}
+
+TEST(CheckRelativelyCloseFailsOnNotEqual)
+{
+ bool failure = false;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+ CHECK_RELATIVELY_CLOSE (1.0f, 1.1f, 0.01f);
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(failure);
+}
+
+TEST(CheckRelativelyCloseFailsOnException)
+{
+ bool failure = false;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+ CHECK_RELATIVELY_CLOSE ((float)ThrowingFunction(), 1.0001f, 0.1f);
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(failure);
+}
+
+TEST(CheckRelativelyCloseFailureContainsCorrectDetails)
+{
+ int line = 0;
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ UnitTest::TestDetails testDetails("test", "suite", "filename", -1);
+ ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+ CHECK_RELATIVELY_CLOSE (1.0f, 1.1f, 0.01f); line = __LINE__;
+ }
+
+ CHECK_EQUAL("test", reporter.lastFailedTest);
+ CHECK_EQUAL("suite", reporter.lastFailedSuite);
+ CHECK_EQUAL("filename", reporter.lastFailedFile);
+ CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckRelativelyCloseFailureBecauseOfExceptionContainsCorrectDetails)
+{
+ int line = 0;
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ UnitTest::TestDetails testDetails("closeTest", "closeSuite", "filename", -1);
+ ScopedCurrentTest scopedResults(testResults, &testDetails);
+ CHECK_RELATIVELY_CLOSE ((float)ThrowingFunction(), 1.0001f, 0.1f); line = __LINE__;
+ }
+
+ CHECK_EQUAL("closeTest", reporter.lastFailedTest);
+ CHECK_EQUAL("closeSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("filename", reporter.lastFailedFile);
+ CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckRelativelyCloseFailureBecauseOfExceptionIncludesCheckContents)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+ CHECK_RELATIVELY_CLOSE ((float)ThrowingFunction(), 1.0001f, 0.1f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "(float)ThrowingFunction()"));
+ CHECK(strstr(reporter.lastFailedMessage, "1.0001f"));
+}
+
+TEST(CheckRelativelyCloseDoesNotHaveSideEffectsWhenPassing)
+{
+ g_sideEffect = 0;
+ {
+ UnitTest::TestResults testResults;
+ ScopedCurrentTest scopedResults(testResults);
+ CHECK_RELATIVELY_CLOSE (1, FunctionWithSideEffects(), 0.1f);
+ }
+ CHECK_EQUAL(1, g_sideEffect);
+}
+
+TEST(CheckRelativelyCloseDoesNotHaveSideEffectsWhenFailing)
+{
+ g_sideEffect = 0;
+ {
+ UnitTest::TestResults testResults;
+ ScopedCurrentTest scopedResults(testResults);
+ CHECK_RELATIVELY_CLOSE (2, FunctionWithSideEffects(), 0.1f);
+ }
+ CHECK_EQUAL(1, g_sideEffect);
+}
+
class ThrowingObject
{
public:
@@ -336,7 +447,6 @@
}
};
-
TEST(CheckArrayCloseSucceedsOnEqual)
{
bool failure = true;
@@ -475,7 +585,144 @@
CHECK(strstr(reporter.lastFailedMessage, "obj"));
}
+TEST(CheckArrayRelativelyCloseSucceedsOnEqual)
+{
+ bool failure = true;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+ const float data[4] = { 0, 1, 2, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data, data, 4, 0.01f);
+ failure = (testResults.GetFailureCount() > 0);
+ }
+ CHECK(!failure);
+}
+
+TEST(CheckArrayRelativelyCloseFailsOnNotEqual)
+{
+ bool failure = false;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ int const data1[4] = { 0, 1, 2, 3 };
+ int const data2[4] = { 0, 1, 3, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data1, data2, 4, 0.01f);
+
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(failure);
+}
+
+TEST(CheckArrayRelativelyCloseFailureIncludesCheckExpectedAndActual)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ int const data1[4] = { 0, 1, 2, 3 };
+ int const data2[4] = { 0, 1, 3, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data1, data2, 4, 0.01f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]"));
+ CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]"));
+}
+
+TEST(CheckArrayRelativelyCloseFailureContainsCorrectDetails)
+{
+ int line = 0;
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ UnitTest::TestDetails testDetails("arrayRelativelyCloseTest", "arrayRelativelyCloseSuite", "filename", -1);
+ ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+ int const data1[4] = { 0, 1, 2, 3 };
+ int const data2[4] = { 0, 1, 3, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data1, data2, 4, 0.01f); line = __LINE__;
+ }
+
+ CHECK_EQUAL("arrayRelativelyCloseTest", reporter.lastFailedTest);
+ CHECK_EQUAL("arrayRelativelyCloseSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("filename", reporter.lastFailedFile);
+ CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArrayRelativelyCloseFailureBecauseOfExceptionContainsCorrectDetails)
+{
+ int line = 0;
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ UnitTest::TestDetails testDetails("arrayRelativelyCloseTest", "arrayRelativelyCloseSuite", "filename", -1);
+ ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+ int const data[4] = { 0, 1, 2, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data, ThrowingObject(), 4, 0.01f); line = __LINE__;
+ }
+
+ CHECK_EQUAL("arrayRelativelyCloseTest", reporter.lastFailedTest);
+ CHECK_EQUAL("arrayRelativelyCloseSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("filename", reporter.lastFailedFile);
+ CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArrayRelativelyCloseFailureIncludesTolerance)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ float const data1[4] = { 0, 1, 2, 3 };
+ float const data2[4] = { 0, 1, 3, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data1, data2, 4, 0.01f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "0.01"));
+}
+
+
+TEST(CheckArrayRelativelyCloseFailsOnException)
+{
+ bool failure = false;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[4] = { 0, 1, 2, 3 };
+ ThrowingObject obj;
+ CHECK_ARRAY_RELATIVELY_CLOSE (data, obj, 3, 0.01f);
+
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(failure);
+}
+
+TEST(CheckArrayRelativelyCloseFailureOnExceptionIncludesCheckContents)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[4] = { 0, 1, 2, 3 };
+ ThrowingObject obj;
+ CHECK_ARRAY_RELATIVELY_CLOSE (data, obj, 3, 0.01f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "data"));
+ CHECK(strstr(reporter.lastFailedMessage, "obj"));
+}
+
TEST(CheckArrayEqualSuceedsOnEqual)
{
bool failure = true;
@@ -613,6 +860,33 @@
CHECK_EQUAL(1, g_sideEffect);
}
+TEST(CheckArrayRelativelyCloseDoesNotHaveSideEffectsWhenPassing)
+{
+ g_sideEffect = 0;
+ {
+ UnitTest::TestResults testResults;
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[] = { 0, 1, 2, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f);
+ }
+ CHECK_EQUAL(1, g_sideEffect);
+}
+
+TEST(CheckArrayRelativelyCloseDoesNotHaveSideEffectsWhenFailing)
+{
+ g_sideEffect = 0;
+ {
+ UnitTest::TestResults testResults;
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[] = { 0, 1, 3, 3 };
+ CHECK_ARRAY_RELATIVELY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f);
+ }
+
+ CHECK_EQUAL(1, g_sideEffect);
+}
+
class ThrowingObject2D
{
public:
@@ -622,7 +896,6 @@
}
};
-
TEST(CheckArray2DCloseSucceedsOnEqual)
{
bool failure = true;
@@ -763,6 +1036,146 @@
CHECK(strstr(reporter.lastFailedMessage, "obj"));
}
+TEST(CheckArray2DRelativelyCloseSucceedsOnEqual)
+{
+ bool failure = true;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[2][2] = { {0, 1}, {2, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data, data, 2, 2, 0.01f);
+
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(!failure);
+}
+
+TEST(CheckArray2DRelativelyCloseFailsOnNotEqual)
+{
+ bool failure = false;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ int const data1[2][2] = { {0, 1}, {2, 3} };
+ int const data2[2][2] = { {0, 1}, {3, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data1, data2, 2, 2, 0.01f);
+
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(failure);
+}
+
+TEST(CheckArray2DRelativelyCloseFailureIncludesCheckExpectedAndActual)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ int const data1[2][2] = { {0, 1}, {2, 3} };
+ int const data2[2][2] = { {0, 1}, {3, 3} };
+
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data1, data2, 2, 2, 0.01f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "xpected [ [ 0 1 ] [ 2 3 ] ]"));
+ CHECK(strstr(reporter.lastFailedMessage, "was [ [ 0 1 ] [ 3 3 ] ]"));
+}
+
+TEST(CheckArray2DRelativelyCloseFailureContainsCorrectDetails)
+{
+ int line = 0;
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ UnitTest::TestDetails testDetails("array2DRelativelyCloseTest", "array2DRelativelyCloseSuite", "filename", -1);
+ ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+ int const data1[2][2] = { {0, 1}, {2, 3} };
+ int const data2[2][2] = { {0, 1}, {3, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data1, data2, 2, 2, 0.01f); line = __LINE__;
+ }
+
+ CHECK_EQUAL("array2DRelativelyCloseTest", reporter.lastFailedTest);
+ CHECK_EQUAL("array2DRelativelyCloseSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("filename", reporter.lastFailedFile);
+ CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArray2DRelativelyCloseFailureBecauseOfExceptionContainsCorrectDetails)
+{
+ int line = 0;
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ UnitTest::TestDetails testDetails("array2DRelativelyCloseTest", "array2DRelativelyCloseSuite", "filename", -1);
+ ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+ const float data[2][2] = { {0, 1}, {2, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data, ThrowingObject2D(), 2, 2, 0.01f); line = __LINE__;
+ }
+
+ CHECK_EQUAL("array2DRelativelyCloseTest", reporter.lastFailedTest);
+ CHECK_EQUAL("array2DRelativelyCloseSuite", reporter.lastFailedSuite);
+ CHECK_EQUAL("filename", reporter.lastFailedFile);
+ CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArray2DRelativelyCloseFailureIncludesTolerance)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ float const data1[2][2] = { {0, 1}, {2, 3} };
+ float const data2[2][2] = { {0, 1}, {3, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data1, data2, 2, 2, 0.01f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "0.01"));
+}
+
+TEST(CheckArray2DRelativelyCloseFailsOnException)
+{
+ bool failure = false;
+ {
+ RecordingReporter reporter;
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[2][2] = { {0, 1}, {2, 3} };
+ ThrowingObject2D obj;
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data, obj, 2, 2, 0.01f);
+
+ failure = (testResults.GetFailureCount() > 0);
+ }
+
+ CHECK(failure);
+}
+
+TEST(CheckArray2DRelativelyCloseFailureOnExceptionIncludesCheckContents)
+{
+ RecordingReporter reporter;
+ {
+ UnitTest::TestResults testResults(&reporter);
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[2][2] = { {0, 1}, {2, 3} };
+ ThrowingObject2D obj;
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data, obj, 2, 2, 0.01f);
+ }
+
+ CHECK(strstr(reporter.lastFailedMessage, "data"));
+ CHECK(strstr(reporter.lastFailedMessage, "obj"));
+}
+
float const* const* FunctionWithSideEffects3()
{
++g_sideEffect;
@@ -798,4 +1211,30 @@
CHECK_EQUAL(1, g_sideEffect);
}
+TEST(CheckArrayRelatively2DCloseDoesNotHaveSideEffectsWhenPassing)
+{
+ g_sideEffect = 0;
+ {
+ UnitTest::TestResults testResults;
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[2][2] = { {0, 1}, {2, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f);
+ }
+ CHECK_EQUAL(1, g_sideEffect);
}
+
+TEST(CheckArray2DRelativelyCloseDoesNotHaveSideEffectsWhenFailing)
+{
+ g_sideEffect = 0;
+ {
+ UnitTest::TestResults testResults;
+ ScopedCurrentTest scopedResults(testResults);
+
+ const float data[2][2] = { {0, 1}, {3, 3} };
+ CHECK_ARRAY2D_RELATIVELY_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f);
+ }
+ CHECK_EQUAL(1, g_sideEffect);
+}
+
+}
Index: src/CheckMacros.h
===================================================================
--- src/CheckMacros.h (revision 207)
+++ src/CheckMacros.h (working copy)
@@ -19,6 +19,10 @@
#error UnitTest++ redefines CHECK_CLOSE
#endif
+#ifdef CHECK_RELATIVELY_CLOSE
+ #error UnitTest++ redefines CHECK_CLOSE
+#endif
+
#ifdef CHECK_ARRAY_EQUAL
#error UnitTest++ redefines CHECK_ARRAY_EQUAL
#endif
@@ -27,10 +31,18 @@
#error UnitTest++ redefines CHECK_ARRAY_CLOSE
#endif
+#ifdef CHECK_ARRAY_RELATIVELY_CLOSE
+ #error UnitTest++ redefines CHECK_ARRAY_CLOSE
+#endif
+
#ifdef CHECK_ARRAY2D_CLOSE
#error UnitTest++ redefines CHECK_ARRAY2D_CLOSE
#endif
+#ifdef CHECK_ARRAY2D_RELATIVELY_CLOSE
+ #error UnitTest++ redefines CHECK_ARRAY2D_CLOSE
+#endif
+
#define CHECK(value) \
do \
{ \
@@ -68,6 +80,18 @@
} \
} while (0)
+#define CHECK_RELATIVELY_CLOSE(expected, actual, tolerance) \
+ do \
+ { \
+ try { \
+ UnitTest::CheckRelativelyClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+ } \
+ catch (...) { \
+ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+ "Unhandled exception in CHECK_CLOSE(" #expected ", " #actual ")"); \
+ } \
+ } while (0)
+
#define CHECK_ARRAY_EQUAL(expected, actual, count) \
do \
{ \
@@ -92,6 +116,18 @@
} \
} while (0)
+#define CHECK_ARRAY_RELATIVELY_CLOSE(expected, actual, count, tolerance) \
+ do \
+ { \
+ try { \
+ UnitTest::CheckArrayRelativelyClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+ } \
+ catch (...) { \
+ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+ "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \
+ } \
+ } while (0)
+
#define CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \
do \
{ \
@@ -104,6 +140,17 @@
} \
} while (0)
+#define CHECK_ARRAY2D_RELATIVELY_CLOSE(expected, actual, rows, columns, tolerance) \
+ do \
+ { \
+ try { \
+ UnitTest::CheckArray2DRelativelyClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+ } \
+ catch (...) { \
+ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+ "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \
+ } \
+ } while (0)
#define CHECK_THROW(expression, ExpectedExceptionType) \
do \
------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
unittest-cpp-devel mailing list
unittest-cpp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/unittest-cpp-devel