Download - Unit tests final
![Page 1: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/1.jpg)
Практики надежного модульного тестирования
для С++Юрий Ефимочев
![Page 2: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/2.jpg)
О себе
Ведущий разработчик/архитектор в компании SolarWinds, в бэкап-решении MAXBackup.Специализация: высоконагруженные отказоустойчивые системы на C++
![Page 3: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/3.jpg)
Польза > Затраты
Что такое модульные тесты?
Модульное тестирование(unit testing) - это процесс, позволяющий проверить на корректность отдельные модули программы.
![Page 4: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/4.jpg)
● Раннее обнаружение ошибок● Обнаружение регрессионных ошибок● Моделирование сложных сценариев● Получение оценки производительности● Динамический анализ кода(valgrind, …)
Обнаружение ошибок
![Page 5: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/5.jpg)
Дизайн
![Page 6: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/6.jpg)
Дизайн
● Модульность● Поощрение рефакторинга● Ускорение разработки за счет повышения
качества кода● Foolproof design
![Page 7: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/7.jpg)
Пример: foolproof design class ITransactionController { public: virtual void BeginTransaction() = 0; virtual void CommitTransaction() = 0; virtual void RollbackTransaction() = 0;
virtual ~ITransactionController() {} };
![Page 8: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/8.jpg)
Пример: foolproof design BOOST_AUTO_TEST_CASE(DoubleBeginTest) { controller.BeginTransaction(); BOOST_REQUIRE_THROW(controller.BeginTransaction()); }
BOOST_AUTO_TEST_CASE(OutOfOrderCommitTest) { BOOST_REQUIRE_THROW(controller.CommitTransaction()); }
BOOST_AUTO_TEST_CASE(OutOfOrderRollbackTest) { BOOST_REQUIRE_THROW(controller.RollbackTransaction()); }
![Page 9: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/9.jpg)
Пример: foolproof design class ITransactionGuard { public: virtual void Commit() = 0;
virtual ~ITransactionGuard() {} };
typedef std::unique_ptr<ITransactionGuard> ITransactionGuardPtr;
class ITransactionController { public: virtual ITransactionGuardPtr BeginTransaction() = 0;
virtual ~ITransactionController() {} };
![Page 10: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/10.jpg)
Пример: foolproof design{ ITransactionGuardPtr guard = controller.BeginTransaction();
// do something
guard.Commit(); }
![Page 11: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/11.jpg)
Документация
![Page 12: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/12.jpg)
Документация
● Актуальная документация● Верификация на этапе компиляции● Готовые сценарии использования
![Page 13: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/13.jpg)
Хороший тест:
● Актуален○ Запускается при сборке○ Ошибка теста = ошибка компиляции○ Покрытие кода тестами контролируется
![Page 14: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/14.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку
○ Выполняется быстро○ Не спамит в лог компиляции○ Код соответствует guideline-ам○ Результат не зависит от окружения
![Page 15: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/15.jpg)
Пример BOOST_AUTO_TEST_CASE(DnsResolverTest) { DnsResolver resolver; BOOST_REQUIRE_NO_THROW(resolver.Resolve("www.google.com")); }
![Page 16: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/16.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку
○ Выполняется быстро○ Не спамит в лог компиляции○ Код соответствует guideline-ам○ Результат не зависит от окружения○ Ведет себя детерминировано
![Page 17: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/17.jpg)
Пример void SimpleTask(std::atomic<int>& counter) { ++counter; }
BOOST_AUTO_TEST_CASE(ThreadPoolTest) { int const TaskCount = 100;
ThreadPool pool(4);
std::atomic<int> processedCount = 0;
for (int index = 0; index < TaskCount; ++index) { pool.AddTask(std::bind(&SimpleTask, std::ref(processedCount))); }
ThreadHelper::Sleep(Time::Seconds(1));
BOOST_CHECK_EQUAL(processedCount, TaskCount); }
![Page 18: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/18.jpg)
Пример BOOST_AUTO_TEST_CASE(EncryptionTest) { int const IterationsCount = 1000000;
for (int index = 0; index < IterationsCount; ++index) { std::string const phrase = GenerateRandomPhrase(); BOOST_CHECK(Decrypt(Encrypt(phrase)) == phrase); } }
![Page 19: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/19.jpg)
Пример BOOST_AUTO_TEST_CASE(EncryptionTest) { int const IterationsCount = 1000000;
for (int index = 0; index < IterationsCount; ++index) { std::string const phrase = GenerateRandomPhrase(); BOOST_CHECK_EQUAL(Decrypt(Encrypt(phrase)), phrase); } }
![Page 20: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/20.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку
○ Выполняется быстро○ Не спамит в лог компиляции○ Код соответствует guideline-ам○ Результат не зависит от окружения○ Ведет себя детерминировано○ Ошибки информативны
![Page 21: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/21.jpg)
Информативные ошибки
void CheckItem(Item const& item) { BOOST_REQUIRE(0 < item.Id && item.Id < 1000 && 0 < item.Name.size() && item.Name.size() < 50); // error }
BOOST_AUTO_TEST_CASE(CreateTest) { CheckItem(factory.Create(ParameterSet1)); CheckItem(factory.Create(ParameterSet2)); CheckItem(factory.Create(ParameterSet3)); }
BOOST_AUTO_TEST_CASE(SomeOtherTest) { // ... CheckItem(...); // ... }
![Page 22: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/22.jpg)
Информативные ошибки
bool CheckItem(Item const& item) { return 0 < item.Id && item.Id < 1000 && 0 < item.Name.size() && item.Name.size() < 50; }
BOOST_AUTO_TEST_CASE(CreateTest) { BOOST_REQUIRE(CheckItem(factory.Create(ParameterSet1))); // error BOOST_REQUIRE(CheckItem(factory.Create(ParameterSet2))); BOOST_REQUIRE(CheckItem(factory.Create(ParameterSet3))); }
![Page 23: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/23.jpg)
Информативные ошибки
bool CheckItem(Item const& item) { return 0 < item.Id && item.Id < 1000 && 0 < item.Name.size() && item.Name.size() < 50; }
BOOST_AUTO_TEST_CASE(CreateTest) { BOOST_CHECK(CheckItem(factory.Create(ParameterSet1))); // error BOOST_CHECK(CheckItem(factory.Create(ParameterSet2))); BOOST_CHECK(CheckItem(factory.Create(ParameterSet3))); // error }
![Page 24: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/24.jpg)
Информативные ошибки
#define CHECK_ITEM(item) \ BOOST_CHECK_GT(item.Id, 0); \ BOOST_CHECK_LT(item.Id, 1000); \ BOOST_CHECK_GT(item.Name.size(), 0); \ BOOST_CHECK_LT(item.Name.size(), 50);
BOOST_AUTO_TEST_CASE(CreateTest) { CHECK_ITEM(factory.Create(ParameterSet1)); // error: invalid id CHECK_ITEM(factory.Create(ParameterSet2)); CHECK_ITEM(factory.Create(ParameterSet3)); // error: invalid name }
![Page 25: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/25.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку● Прост для понимания
○ Хорошо структурирован
![Page 26: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/26.jpg)
Примерclass IUserManager{public: virtual int AddUser(UserInfo const& user) = 0; virtual void UpdateUser(UserInfo const& user) = 0; virtual void DeleteUser(int const id) = 0;
virtual UserInfo GetUserById(int const id) const = 0; virtual UserInfoIteratorPtr EnumerateUsers() const = 0;
virtual ~IUserManager() {}};
![Page 27: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/27.jpg)
Пример: организация тестов BOOST_AUTO_TEST_SUITE(UserManagerTestSuite);
BOOST_AUTO_TEST_CASE(Test) { // create manager // add 20 users // test EnumerateUsers // test GetUserById // add 2 more users // test add special case // test EnumerateUsers // test GetUserById // update 10 users // test update special case // test EnumerateUsers // test GetUserById // delete 10 users // ... }
BOOST_AUTO_TEST_SUITE_END()
![Page 28: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/28.jpg)
Пример: организация тестов BOOST_AUTO_TEST_SUITE(UserManagerTestSuite)
BOOST_AUTO_TEST_CASE(InsertTest) BOOST_AUTO_TEST_CASE(InsertNonUniqueTest) BOOST_AUTO_TEST_CASE(InsertWithCustomIdTest) BOOST_AUTO_TEST_CASE(InsertWithAlreadyExistingIdTest)
BOOST_AUTO_TEST_CASE(UpdateTest) BOOST_AUTO_TEST_CASE(UpdateWithInvalidValueTest) BOOST_AUTO_TEST_CASE(UpdateNonExistingUserTest)
BOOST_AUTO_TEST_CASE(DeleteTest) BOOST_AUTO_TEST_CASE(DeleteNonExistingUserTest)
BOOST_AUTO_TEST_CASE(GetUserByIdTest) BOOST_AUTO_TEST_CASE(GetNonExistingUserByIdTest)
BOOST_AUTO_TEST_CASE(EnumerateTest) BOOST_AUTO_TEST_CASE(EnumerateEmptyCollectionTest)
BOOST_AUTO_TEST_SUITE_END()
![Page 29: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/29.jpg)
Пример: тест-сценарий BOOST_AUTO_TEST_CASE(EnumerateTest) { // Given manager.AddUser(UserInfo1); manager.AddUser(UserInfo2); manager.AddUser(UserInfo3);
// When manager.DeleteUser(UserInfo2.Id);
// Then BOOST_CHECK_EQUAL(manager.Enumerate().Size(), 2); BOOST_CHECK_EQUAL(manager.GetUserById(UserInfo1.Id), UserInfo1); BOOST_CHECK_THROW(manager.GetUserById(UserInfo2.Id)); BOOST_CHECK_EQUAL(manager.GetUserById(UserInfo3.Id), UserInfo3); }
![Page 30: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/30.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку● Прост для понимания
○ Хорошо структурирован○ Минималистичен
![Page 31: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/31.jpg)
Пример: fixture BOOST_AUTO_TEST_SUITE(UserManagerTestSuite);
BOOST_AUTO_TEST_CASE(UpdateTest) { ManagerFactory const factory; IUserManagerPtr manager = factory.CreateUserManager();
// ... }
BOOST_AUTO_TEST_CASE(DeleteTest) { ManagerFactory const factory; IUserManagerPtr manager = factory.CreateUserManager();
// ... }
BOOST_AUTO_TEST_SUITE_END()
![Page 32: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/32.jpg)
Пример: fixture struct Fixture { Fixture() : Manager(MangerFactory().CreateUserManager()) {}
IUserManagerPtr Manager; }
BOOST_FIXTURE_TEST_SUITE(UserManagerTestSuite, Fixture);
BOOST_AUTO_TEST_CASE(UpdateTest) { // ... }
BOOST_AUTO_TEST_CASE(DeleteTest) { // ...}
BOOST_FIXTURE_TEST_SUITE_END()
![Page 33: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/33.jpg)
Пример: излишняя сложность BOOST_AUTO_TEST_CASE(Test) { int id = 0;
++id; BOOST_CHECK_EQUAL(manager.AddUser(Names[id]), id); ++id; BOOST_CHECK_EQUAL(manager.AddUser(Names[id]), id); ++id; BOOST_CHECK_EQUAL(manager.AddUser(Names[id]), id);
while (id >= 0) { BOOST_CHECK_EQUAL(manager.GetUserById(id).Name, Names[id]); --id; } }
![Page 34: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/34.jpg)
Пример: излишняя сложность BOOST_AUTO_TEST_CASE(Test) { BOOST_CHECK_EQUAL(manager.AddUser(Name1), 1); BOOST_CHECK_EQUAL(manager.AddUser(Name2), 2); BOOST_CHECK_EQUAL(manager.AddUser(Name3), 3);
BOOST_CHECK_EQUAL(manager.GetUserById(1).Name, Name1); BOOST_CHECK_EQUAL(manager.GetUserById(2).Name, Name2); BOOST_CHECK_EQUAL(manager.GetUserById(3).Name, Name3); }
![Page 35: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/35.jpg)
Пример: повторяющиеся проверки BOOST_AUTO_TEST_CASE(DeleteTest) { BOOST_CHECK_EQUAL(manager.AddUser(...), 1); BOOST_CHECK_EQUAL(manager.AddUser(...), 2); BOOST_CHECK_EQUAL(manager.AddUser(...), 3); BOOST_CHECK_EQUAL(manager.AddUser(...), 4);
BOOST_CHECK_NO_THROW(manager.DeleteUser(1)); BOOST_CHECK_NO_THROW(manager.DeleteUser(2)); BOOST_CHECK_NO_THROW(manager.DeleteUser(3)); BOOST_CHECK_NO_THROW(manager.DeleteUser(4)); }
BOOST_AUTO_TEST_CASE(DeleteTest) { BOOST_CHECK_EQUAL(manager.AddUser(...), 1); BOOST_CHECK_NO_THROW(manager.DeleteUser(1)); }
![Page 36: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/36.jpg)
Пример: ортогональные тесты BOOST_AUTO_TEST_CASE(UpdateTest) { BOOST_CHECK_EQUAL(manager.AddUser(UserInfo1), 1); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo2), 2); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo3), 3); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo4), 4); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo5), 5);
// ... }
BOOST_AUTO_TEST_CASE(DeleteTest) { BOOST_CHECK_EQUAL(manager.AddUser(UserInfo1), 1); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo2), 2); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo3), 3); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo4), 4); BOOST_CHECK_EQUAL(manager.AddUser(UserInfo5), 5);
// ... }
![Page 37: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/37.jpg)
Пример: ортогональные тесты BOOST_AUTO_TEST_CASE(UpdateTest) { manager.AddUser(UserInfo1); manager.AddUser(UserInfo2); manager.AddUser(UserInfo3);
// ... }
BOOST_AUTO_TEST_CASE(DeleteTest) { manager.AddUser(UserInfo1); manager.AddUser(UserInfo2);
// ... }
![Page 38: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/38.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку● Прост для понимания
○ Хорошо структурирован○ Минималистичен○ Самодостаточен
![Page 39: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/39.jpg)
Пример: скрытые данные/проверки
BOOST_FIXTURE_TEST_SUITE(UserManagerTestSuite, Fixture);
BOOST_AUTO_TEST_CASE(Test) { ReadDataFromFile("./Data.user", Manager); ValidateData(Manager); }
BOOST_FIXTURE_TEST_SUITE_END()
![Page 40: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/40.jpg)
std::string Encrypt(std::string const& data) { return data; // todo: implement later }
std::string Decrypt(std::string const& data) { return data; // todo: implement later }
Пример: неявные проверки
std::string const SecretPhrase = "secret phrase";
BOOST_AUTO_TEST_CASE(Test) { BOOST_CHECK_EQUAL(Decrypt(Encrypt(SecretPhrase)), SecretPhrase); }
![Page 41: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/41.jpg)
Пример: неявные проверки
std::string const SecretPhrase = "secret phrase"; std::string const EncryptedPhrase = "aL8m52AHJ/Z7Z5G2MkqpIaXOEjRm41OaraiTLYcXM3o=";
BOOST_AUTO_TEST_CASE(EncryptorTest) { BOOST_CHECK_EQUAL(Encrypt(SecretPhrase), EncryptedPhrase); }
BOOST_AUTO_TEST_CASE(DecryptorTest) { BOOST_CHECK_EQUAL(Decrypt(EncryptedPhrase), SecretPhrase); }
![Page 42: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/42.jpg)
Хороший тест:
● Актуален● Не затрудняет разработку● Прост для понимания
○ Хорошо структурирован○ Минималистичен○ Самодостаточен○ Оптимизирован для чтения
![Page 43: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/43.jpg)
Пример: синтаксический сахар BOOST_AUTO_TEST_CASE(TreeTraversalTest) { Tree tree; tree.InsertNode(1); tree.InsertNode(2, 1); tree.InsertNode(3, 2); tree.InsertNode(4, 2); tree.InsertNode(5, 1); tree.InsertNode(6, 5); tree.InsertNode(7, 5);
NodeCollection const nodes = TraversPerOrder(tree);
BOOST_CHECK(nodes.size(), 7); BOOST_CHECK(nodes[0], 1); BOOST_CHECK(nodes[1], 2); BOOST_CHECK(nodes[2], 3); BOOST_CHECK(nodes[3], 4); BOOST_CHECK(nodes[4], 5); BOOST_CHECK(nodes[5], 6); BOOST_CHECK(nodes[6], 7); }
![Page 44: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/44.jpg)
Пример: выразительная сила С++ // http://www.eelis.net/C++/analogliterals.xhtml
assert( ( o-------------o |L \ | L \ | L \ | o-------------o | ! ! ! ! ! o | ! L | ! L | ! L| ! o-------------o ).volume == ( o-------------o | ! ! ! ! ! o-------------o ).area * int(I-------------I) );
![Page 45: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/45.jpg)
Пример: синтаксический сахар BOOST_AUTO_TEST_CASE(TreeTraversalTest) { Tree const tree = Node(1) (Node(2) (Node(3)) (Node(4))) (Node(5) (Node(6)) (Node(7))));
BOOST_CHECK(TraversPreOrder(tree), List(1, 2, 3, 4, 5, 6, 7)); BOOST_CHECK(TraversInOrder(tree), List(3, 2, 4, 1, 6, 5, 7)); BOOST_CHECK(TraversPostOrder(tree), List(3, 4, 2, 6, 7, 5, 1)); }
![Page 46: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/46.jpg)
Пример: синтаксический сахар BOOST_AUTO_TEST_CASE(EnumerateTest) { manager.AddUser(UserInfo("User1", "[email protected]", UserRole::Admin, ...)); manager.AddUser(UserInfo("User2", "[email protected]", UserRole::Reader, ...)); manager.AddUser(UserInfo("User3", "[email protected]", UserRole::Reader, ...));
IUserIteratorPtr iterator = manager.Enumerate(); UserInfo info; BOOST_CHECK(iterator.GetNext(info)); BOOST_CHECK_EQUAL(info.Name, "User1"); BOOST_CHECK(iterator.GetNext(info)); BOOST_CHECK_EQUAL(info.Name, "User2"); BOOST_CHECK(iterator.GetNext(info)); BOOST_CHECK_EQUAL(info.Name, "User3"); }
![Page 47: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/47.jpg)
Пример: синтаксический сахар BOOST_AUTO_TEST_CASE(EnumerateTest) { User("User1"); User("User2"); User("User3");
BOOST_CHECK_EQUAL(Enumerate(), List("User1", "User2", "User3")); }
![Page 48: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/48.jpg)
Пример: синтаксический сахар BOOST_AUTO_TEST_CASE(EnumerateByRoleTest) { User("User1").Role(UserRole::Admin); User("User2").Role(UserRole::Reader); User("User3").Role(UserRole::Reader);
BOOST_CHECK_EQUAL(EnumerateByRole(UserRole::Reader), List("User2", "User3")); }
![Page 49: Unit tests final](https://reader030.vdocuments.site/reader030/viewer/2022021506/586fb2661a28abe57d8b687f/html5/thumbnails/49.jpg)
Рекомендации● Предпочитать check require● Использовать fixture● Оформлять тесты в сценарии● Использовать синтаксический сахар● Убрать все лишнее● Показать все, что нужно для понимания● Написать необходимый минимум тестов