Unittest ++: тест для нескольких возможных значений - PullRequest
1 голос
/ 25 января 2010

В настоящее время я реализую простой трассировщик лучей в C ++. У меня есть класс с именем OrthonormalBasis, который генерирует три ортогональных единичных вектора из одного или двух указанных векторов, например:

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

Я тестирую все свои методы с помощью инфраструктуры Unittest ++. Проблема в том, что существует более одного возможного решения для правильной ортонормированной основы. Например этот тест:

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

иногда это удается, иногда это не удается, потому что векторы v и w также могут иметь отрицательный 1 и по-прежнему представлять действительный ортонормированный базис. Есть ли способ указать несколько ожидаемых значений? Или вы знаете другой способ сделать это?

Важно, чтобы я получил фактические и ожидаемые значения, напечатанные на стандартный вывод, чтобы отладить методы, чтобы это решение не выполняло работу:

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

Ответы [ 3 ]

1 голос
/ 25 января 2010

Конечно, если все, что вы тестируете, это то, является ли ваша база ортонормированной, тогда это то, что вам нужно проверить?

// 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 голосов
/ 25 января 2010

Я бы использовал служебную функцию или класс, чтобы вы могли сделать что-то вроде этого:

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

Учитывая, что интерпретация равенства несколько странная, она должна вывести все значения, которые вы хотите увидеть, без необходимости вводить пользовательский макрос.
Если вас беспокоит EQUAL в этом контексте, пользовательский макрос типа CHECK_CONTAINS() не должен быть слишком сложным для выполнения.

VectorList будет создан как временный, и operator() будет использоваться для вставки значений в содержащийся список Vector с, аналогично Boost.Assign .

Базовый подход:

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();
    }
};
0 голосов
/ 25 января 2010

Одна из возможностей - создать собственную функцию 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);
}
...