настройка юниттест++

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

Я использую UnitTest++: http://unittest-cpp.sourceforge.net/UnitTest++.html

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

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

Код для UnitTest++ довольно прост, и я допускаю, что, вероятно, мог бы понять это, если бы я смотрел на него еще немного, но наверняка кто-то уже понял это? Я пытаюсь придумать способ связать мой argv[] с Test::GetTestList(). Я хотел бы отфильтровать список тестов с помощью аргументов командной строки и запустить только эти тесты.

Хм. Похоже, это просто связанный список. Думаю, я могу просто изувечить его... O(m*n) поиска, m=всего тестов, n=указанных тестов. Что ж. Я продолжаю отвечать на свои вопросы. Моды: я опубликую ответ с реализацией моего решения. Надеюсь, это сэкономит кому-то двадцать минут.

Изменить: похоже, мне действительно нужно использовать предикат:

template <class Predicate>
int RunTestsIf(TestList const& list, char const* suiteName, 
               const Predicate& predicate, int maxTestTimeInMs) const
{
    Test* curTest = list.GetHead();

    while (curTest != 0)
    {
        if (IsTestInSuite(curTest,suiteName) && predicate(curTest))
        {
            RunTest(m_result, curTest, maxTestTimeInMs);
        }

        curTest = curTest->next;
    }

    return Finish();
}   

Таким образом, я могу просто напрямую использовать RunTestsIf().

редактировать: я думаю, что понял это. Ничего себе, первый набег на программирование шаблонов.


person Steven Lu    schedule 27.08.2011    source источник
comment
:( Я искал решение до того, как вы отредактировали свой собственный пост! Я также сомневаюсь, что ваш функтор просто неправильно написан!   -  person Baby Dolphin    schedule 27.08.2011
comment
Извините :( На самом деле я обычно оставляю содержимое своих сообщений и просто расширяю свои сообщения, чтобы люди могли видеть прогресс, происходящий с течением времени (и педалирование). Однако на этот раз это показалось действительно тривиальным и глупым, поэтому я убрал это в интересах. ясности Но я понял это в конце концов, так что все хорошо.   -  person Steven Lu    schedule 27.08.2011


Ответы (1)


Вот мое решение:

namespace UnitTest {
    class ListFilter {
        char **list;
        int n;
    public:
        ListFilter(char **list_, int count) {
            list = list_; n = count;
        }
        bool operator()(const Test* const t) const {
            for (int i=0;i<n;++i) {
                std::string dot_cpp_appended = std::string(list[i]) + ".cpp";
                if (!strcasecmp(t->m_details.testName, list[i]) ||
                        !strcasecmp(t->m_details.suiteName, list[i]) ||
                        !strcasecmp(t->m_details.filename, list[i]) ||
                        !strcasecmp(t->m_details.filename, dot_cpp_appended.c_str())) {
                    // erring on the side of matching more tests
                    return true;
                }
            }
            return false;
        }
    };

    int RunTheseTests(char ** list, int n) {
        TestReporterStdout reporter;
        TestRunner runner(reporter);
        return runner.RunTestsIf(Test::GetTestList(), NULL, ListFilter(list,n), 0);
    }
}

int main(int argc, char *argv[]) {
    if (argc == 1) {
        UnitTest::RunAllTests();
    } else {
        UnitTest::RunTheseTests(argv+1, argc-1); // skip the program's name itself.
    }
}

Единственное, что меня немного беспокоит, это то, что нет чистого способа проверить, не совпали ли какие-либо тестовые сопоставители с чем-либо.

person Steven Lu    schedule 27.08.2011