2010-01-25 7 views
1

Je suis actuellement en train de mettre en œuvre un simple traceur de rayons en C++. J'ai une classe nommée Base de Hilbert, qui génère trois vecteurs unitaires orthogonaux d'un ou deux vecteurs spécifiés, par exemple:Unittest ++: test de plusieurs valeurs possibles

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_); 
} 

Je teste toutes mes méthodes avec unittest ++. Le problème est, qu'il y a plus d'une solution possible pour une base orthonormale valide. Par exemple ce 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()); 
} 

parfois il réussit, parfois, il échoue, car les vecteurs v et w pourraient aussi avoir un 1 négatif, et représentent toujours une base orthonormée valide. Existe-t-il un moyen de spécifier plusieurs valeurs attendues? Ou connaissez-vous une autre façon de faire cela?

Il est important que je reçois les valeurs réelles et attendues imprimées au stdout, afin de déboguer les méthodes donc cette solution ne sera pas faire le travail:

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()); 
} 

Répondre

1

Certes, si tout ce que vous testez est si votre base est orthonormé, alors c'est ce que vous devez tester?

// 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)); 
+0

maintenant c'est tellement simple que je ne pouvais pas y penser. Merci! –

0

Une possibilité est de créer votre propre fonction CHECK_MULTI:

void CHECK_MULTI(TYPE actual, vector<TYPE> expected, const char* message) 
{ 
    for (element in expected) { 
    if (element == actual) { 
     // there's a test here so the test count is correct 
     CHECK(actual, element); 
     return; 
    } 
    } 
    CHECK(actual, expected); 
} 
0

j'utiliser une fonction d'utilité ou de la classe afin que vous puissiez faire quelque chose comme ceci:

CHECK_EQUAL(VectorList(0,0,1)(0,0,-1), onb.v()); 

Étant donné que cette interprétation de l'égalité est quelque peu étrange, elle devrait vous imprimer toutes les valeurs que vous voulez voir sans avoir besoin d'introduire une macro personnalisée.
Si vous êtes préoccupé par EQUAL dans ce contexte, une macro personnalisée comme CHECK_CONTAINS() ne devrait pas être trop difficile à faire.

VectorList serait réalisé sous forme temporaire et operator() être utilisé pour insérer des valeurs dans la liste contenue de Vector s, similaire à Boost.Assign.

approche de base:

class VectorList { 
    std::vector<Vector> data_; 
public: 
    VectorList(double a, double b, double c) { 
     data_.push_back(Vector(a,b,c)); 
    } 
    VectorList& operator()(double a, double b, double c) { 
     data_.push_back(Vector(a,b,c)); 
     return *this; 
    } 
    bool operator==(const Vector& rhs) const { 
     return std::find(data_.begin(), data_.end(), rhs) != data_.end(); 
    } 
}; 
Questions connexes