Базовый diff-diff для теста C ++ - PullRequest
2 голосов
/ 26 июля 2011

У меня есть функция C ++, которая возвращает многострочное std::string. В этом примере я сравниваю каждую строку с известным значением - что-то вроде:

std::string known = "good\netc";
std::string output = "bad\netc";

std::vector<std::string> knownvec;
pystring::splitlines(known, knownvec); // splits on \n

std::vector<std::string> outvec;
pystring::splitlines(output, outvec);

CHECK_EQUAL(osvec.size(), resvec.size());

for(unsigned int i = 0; i < std::min(outvec.size(), knownvec.size()); ++i)
    CHECK_EQUAL(pystring::strip(outvec[i]), pystring::strip(knownvec[i]));

Это работает, но, скажем, добавляется одна новая строка, все последующие утверждения CHECK_EQUAL не выполняются, что затрудняет чтение вывода

Есть ли лучший способ сравнить две строки, в идеале красивым, автономным способом (т.е. не связываться с гигантом difflib или записывать строки в файл и вызывать команду diff!)

[Редактировать] Я использую Довольно простой unittest.h * OpenImageIO.h

Сравниваемые данные в основном либо YAML, либо таблицы соответствия цветов. Вот пример теста - в основном несколько строк заголовков, а затем множество цифр:

 Version 1
 Format any
 Type ...
 LUT:
 Pre {
   0.0
   0.1
   ...
   1.0
 }
 3D {
   0.0
   0.1
   ...
   1.0
 }

Ответы [ 3 ]

1 голос
/ 26 июля 2011

Short:

Для целей модульного тестирования вам просто нужно отметить, что они разные. Модульные тесты не исправляют ошибочные юнит-тесты, программисты исправляют неудачные юнит-тесты.

Long:

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

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

Рассмотрим этот дегенеративный случай:

a b c d e f
d e f a b c

Независимо от того, выберете ли вы одно из этих решений или нет, все зависит от оценки результатов или какого-либо артефакта реализации:

      a b c d e f
d e f a b c

a b c d e f
      d e f a b c

Мое мнение таково: если вам нужно присвоить результат баллу, маловероятно, что юнит-тест применим.

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

Очевидно, что это забавная проблема, но, вероятно, она выходит за рамки модульного тестирования.

1 голос
/ 26 июля 2011

Самое простое, что можно сделать, это выйти из цикла, когда строки больше не совпадают:

for(unsigned int i = 0; i < std::min(outvec.size(), knownvec.size()); ++i)
{
    bool areEqual = pystring::strip(outvec[i]) == pystring::strip(knownvec[i]);
    CHECK_EQUAL(pystring::strip(outvec[i]), pystring::strip(knownvec[i]));
    if (!areEqual)
        break;
}

Если CHECK_EQUAL возвращает логическое значение, то, очевидно, вы можете немного упростить приведенный выше пример.

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

Проверьте этот другой вопрос об информации об алгоритмах и библиотеках diff.

Если вы обнаружите, что самостоятельная реализация алгоритма сравнения не стоит проблем (возможно, это не так), воспользуйтесь библиотеками Google Diff-Match-Patch .

0 голосов
/ 26 июля 2011

Базовый алгоритм сравнения довольно прост в реализации, если не очень эффективен. Эта статья в Википедии является хорошей отправной точкой.

...