Unittest ++: test pour plusieurs valeurs possibles
-
22-09-2019 - |
Question
Je suis exécute actuellement un traceur de rayons simple c ++. J'ai une classe appelée Base de Hilbert, qui génère trois vecteurs unitaires orthogonaux d'un ou de deux vecteurs déterminés, par exemple:
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 ya plus d'une solution possible pour une base orthonormée 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. Y at-il un moyen de spécifier plusieurs valeurs attendues? Ou connaissez-vous une autre façon de le faire?
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() );
}
La solution
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));
Autres conseils
Il est possible 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);
}
J'utilise 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 l'interprétation de l'égalité est un peu bizarre, mais il devrait vous imprimer toutes les valeurs que vous voulez voir sans la nécessité d'introduire une macro personnalisée.
Si vous êtes inquiet au sujet EQUAL
dans ce contexte, une macro personnalisée comme CHECK_CONTAINS()
ne devrait pas être trop difficile à faire.
VectorList
serait construit en tant que temporaire et operator()
être utilisé pour insérer des valeurs dans la liste contenue de Vector
s, semblable à 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();
}
};