I'm using the Catch test framework.
In the introductory blog post the author mentions the following feature:
- Floating point tolerances supported in an easy to use way
I couldn't find any documentation on how to do this. How is this done in Catch?
I'm using the Catch test framework.
In the introductory blog post the author mentions the following feature:
- Floating point tolerances supported in an easy to use way
I couldn't find any documentation on how to do this. How is this done in Catch?
It's simple. There is a class called Approx that lets you do this test in a very readable manner:
#include <limits>
TEST_CASE("demo/approx", "Approx demo") {
double a = 1.0;
double b = a + std::numeric_limits<double>::epsilon();
REQUIRE_FALSE(b == a);
REQUIRE(b == Approx(a));
}
The tolerance can be changed by using the member functions epsilon() and scale() of the Approx object, like so: Approx(a).epsilon(e).
The tolerance is has been customizable since Apr 2011. Approx has two member functions for this: epsilon() and scale(). For example:
REQUIRE(a == Approx(b).epsilon(my_eps));
The tolerance is ε × (scale+max(|a|, |b|)), where scale defaults to 1, so this will pass:
REQUIRE((2+2) == Approx(5).epsilon(0.17));
I know this is an old question, but I just stumbled upon the same problem and found a simple solution. In the Catch.hpp header file where the Approx class is defined (line 2045 at the time of writing), just add the following constructor:
class Approx {
public:
explicit Approx( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_scale( 1.0 ),
m_value( value )
{}
explicit Approx( double value, double epsilon ) // <- New constructor
: m_epsilon( epsilon ),
m_scale( 1.0 ),
m_value( value )
{}
Now you can do this:
TEST_CASE("demo/approx", "Approx demo") {
double myTol = 0.1;
double a = 1.0;
double b = a + myTol;
REQUIRE_FALSE(a == b);
REQUIRE(a == Approx(b, myTol));
}
It is important to note that Approx is now considered deprecated [source]:
The downside to Approx is that it has a couple of issues that we cannot fix without breaking backwards compatibility. Because Catch2 also provides complete set of matchers that implement different floating point comparison methods, Approx is left as-is, is considered deprecated, and should not be used in new code.
As of version 2.10, one should switch to using Matchers.
#include <limits>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
TEST_CASE("demo/matchers", "Matchers demo") {
double a = 1.0;
double b = a + std::numeric_limits<double>::epsilon();
REQUIRE_FALSE(b == a);
REQUIRE_THAT(b, Catch::Matchers::WithinRel(a, std::numeric_limits<double>::epsilon()));
}