Список вызовов методов в производном классе - PullRequest
1 голос
/ 08 февраля 2011

Я занимаюсь разработкой тест-фреймворка. Существует несколько наборов тестов, каждый из которых представляет собой класс с набором функций-членов для каждого отдельного теста.

Я хотел бы найти способ динамически перебирать все тесты в классе.

Идеализированная установка может выглядеть примерно так:

class A : public Test
{
public:
    A() {
        addTest(a);
        addTest(b);
        addTest(c);
    }

    void a() { cout << "A::a" << endl; }
    void b() { cout << "A::b" << endl; }
    void c() { cout << "A::c" << endl; }
};

Метод addTest () добавит свой параметр в список; этот список повторяется позже, и каждый метод запускается.

Есть ли способ достичь этого? Самое близкое, что мы придумали до сих пор, это:

class Test
{
public:
    template <typename T>
    struct UnitTest
    {
        typedef void (T::*P)();
        P f;
        UnitTest(P p) : f(p) {}
    };
    // (this struct simplified: we also include a name and description)

    virtual void run(int testId) = 0;
};

class A : public Test
{
public:
    A() {
        mTests.push_back(UnitTest<A>(&A::a));
        mTests.push_back(UnitTest<A>(&A::b));
        mTests.push_back(UnitTest<A>(&A::c));
    }

    void a() { cout << "a" << endl; }
    void b() { cout << "b" << endl; }
    void c() { cout << "c" << endl; }

    // not ideal - this code has to be repeated in every test-suite
    void run(int testId)
    {
        (this->*(mTests[testId].f))();
    }
    vector<UnitTest<A>> mTests;
};

Чтобы вызвать один тест на каждую итерацию основного цикла выполнения:

a->run(mTestId++);

Это не идеально, потому что каждый набор тестов (класс) должен повторять код run () и иметь собственный член mTests.

Есть ли способ приблизиться к идеалу?

1 Ответ

1 голос
/ 08 февраля 2011

Сделайте каждый тест функтором или функциональным объектом .Создайте контейнер указателей на тесты, а затем переберите контейнер:

struct Test_Base_Class
{
  virtual bool Execute(void) = 0;
};

typedef std::vector<Test_Base_Class *> Container_Of_Tests;

struct Test_Engine
{
  Container_Of_Tests tests_to_run;

  void Add_Test(Test_Base_Class * p_new_test)
  {
    tests_to_run.push_back(p_new_test);
  }

  void Run_Tests(void)
  {
    Container_Of_Tests::iterator iter;
    for (iter = tests_to_run.begin();
         iter != tests_to_run.end();
         ++iter)
    {
       (*iter)->Execute(); // Invoke the Execute method on a test.
    }
    return;
  }
}

Это основа.В настоящее время я использую этот шаблон, но расширил его, добавив метод Resume () и отчеты о состоянии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...