Как проверить, что генератор последовательности будет генерировать ожидаемый элемент? - PullRequest
0 голосов
/ 07 ноября 2019

У меня есть класс B, который генерирует A. Я знаю, что в определенной настройке, если я вызову его 3 раза, он сгенерирует конкретный экземпляр A (expected_a), но я не знаю, где в последовательности.

Я бы хотелнаписать код для юнит-теста, например:

A expected_a(...);

B b;

std::set<A> set_of_a{ b.nextA() , b.nextA(), b.nextA() };

EXPECT_TRUE(set_of_a.count(expected_a) == 1);

Но использование set требует реализации A::operator<(). operator< может быть легко реализовано, НО тогда я пишу производственный код, чтобы выполнить тест, который я не люблю / не хочу делать.

Я пробовал с unordered_set, который не требует operator<но требует hash() реализовано.

BTW A::operator= уже внедрено в производство.

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

Как я могу элегантно написать этот тест, не прибегая к реализации специфических операторов теста?

Ответы [ 3 ]

2 голосов
/ 07 ноября 2019

Вы можете использовать пользовательскую функцию сравнения, локальную для модульного теста:

A expected_a(...);

B b;
auto comparator = [](const auto& lhs, const auto& rhs) { /*comparator code*/};
std::set<A, decltype(comparator)> set_of_a({b.nextA() , b.nextA(), b.nextA()}, comparator);

EXPECT_TRUE(set_of_a.count(expected_a) == 1);
2 голосов
/ 07 ноября 2019

Вы можете просто использовать другой контейнер и std::count:

A expected_a(...);
B b;

std::array<A, 3> arr_of_as{ b.nextA() , b.nextA(), b.nextA() };

EXPECT_TRUE(std::count(std::begin(arr_of_as), std::end(arr_of_as), expected_a) > 0);

Вы даже не можете хранить их:

A expected_a(...);
B b;

int count_a = 0;
for (int i = 0; i < 3; ++i) {
    count_a += b.nextA() == expected_a;
}
EXPECT_TRUE(count_a > 0);

Обратите внимание, что в обеих версиях это число как минимум один expected_a, но может быть и больше, что соответствует вашей set версии.

1 голос
/ 07 ноября 2019

GoogleMock покрывает вас UnorderedElementsAre и UnorderedElementsAreArray

std::vector<A> expected {expectedA1, expectedA2};
std::vector<A> uut {b.nextA(), b.nextA()};
EXPECT_THAT(uut, ::testing::UnorderedElementsAreArray(expected));
EXPECT_THAT(uut, ::testing::UnorderedElementsAre(expectedA1, expectedA2));

Он проверит, все ли элементы находятся в предоставленном контейнере в любом порядке.


Есливам нужно проверить только один элемент из набора, тогда существует Contains() совпадение:

std::vector<A> uut {b.nextA(), b.nextA()};
EXPECT_THAT(uut, ::testing::Contains(expected_a));
...