Search code examples
c++debuggingraytracingunittest++orthogonal

Unittest++: test for multiple possible values


i am currently implementing a simple ray tracer in c++. I have a class named OrthonormalBasis, which generates three orthogonal unit vectors from one or two specified vectors, for example:

void
OrthonormalBasis::init_from_u ( const Vector& u )
{
    Vector n(1,0,0);
    Vector m(0,1,0);
    u_ = unify(u);
    v_ = cross(u_,n);
    if ( v_.length() < ONB_EPSILON )
        v_ = cross(u_,m);
    w_ = cross(u_,v_);
}

I am testing all my methods with the Unittest++ framework. The Problem is, that there is more than one possible solution for a valid orthonormal basis. For example this test:

TEST ( orthonormalbasis__should_init_from_u )
{
    Vector u(1,0,0);
    OrthonormalBasis onb;

    onb.init_from_u(u);

    CHECK_EQUAL( Vector( 1, 0, 0 ), onb.u() );
    CHECK_EQUAL( Vector( 0, 0, 1 ), onb.v() );
    CHECK_EQUAL( Vector( 0, 1, 0 ), onb.w() );
}

sometimes it succeeds, sometimes it fails, because the vectors v and w could also have a negative 1, and still represent a valid orthonormal basis. Is there a way to specify multiple expected values? Or do you know another way to do that?

It is important, that i get the actual and expected values printed to the stdout, in order to debug the methods so this solution won't do the job:

TEST ( orthonormalbasis__should_init_from_u )
{
    Vector u(1,0,0);
    OrthonormalBasis onb;

    onb.init_from_u(u);

    CHECK_EQUAL( Vector( 1, 0, 0 ), onb.u() );
    CHECK(
        Vector( 0, 0, 1 ) == onb.v() ||
        Vector( 0, 0,-1 ) == onb.v() );
    CHECK(
        Vector( 0, 1, 0 ) == onb.w() ||
        Vector( 0,-1, 0 ) == onb.w() );
}

Solution

  • Surely if all you are testing is whether your basis is orthonormal, then that's what you need to test?

    // check orthogonality
    
    CHECK_EQUAL( 0, dot(onb.u(), onb.v));
    CHECK_EQUAL( 0, dot(onb.u(), onb.w));
    CHECK_EQUAL( 0, dot(onb.v(), onb.w));
    
    // check normality
    
    CHECK_EQUAL( 1, dot(onb.u(), onb.u));
    CHECK_EQUAL( 1, dot(onb.v(), onb.v));
    CHECK_EQUAL( 1, dot(onb.w(), onb.w));