Ответ
В C++ проектах я в основном работал со следующими библиотеками для модульного тестирования:
-
Google Test (gtest) с Google Mock (gmock): Это мой основной выбор для больших проектов. Фреймворк предоставляет богатый набор макросов для утверждений (
ASSERT_*,EXPECT_*), поддержку фикстур, параметризованных тестов и мощную систему мок-объектов.#include <gtest/gtest.h> #include <gmock/gmock.h> TEST(CalculatorTest, AddsTwoNumbers) { EXPECT_EQ(Add(2, 3), 5); } class MockDatabase : public DatabaseInterface { public: MOCK_METHOD(std::string, FetchName, (int id), (override)); }; TEST(UserTest, GetsUserName) { MockDatabase db; EXPECT_CALL(db, FetchName(42)) .WillOnce(Return("John Doe")); // Тестируемый код, использующий db } -
Catch2: Отличный современный header-only фреймворк. Я использовал его в небольших проектах или библиотеках из-за простоты интеграции (просто добавить один заголовочный файл) и читаемого синтаксиса BDD-стиля.
#define CATCH_CONFIG_MAIN #include <catch2/catch_all.hpp> TEST_CASE("Vector can be sized and resized", "[vector]") { std::vector<int> v(5); REQUIRE(v.size() == 5); REQUIRE(v.capacity() >= 5); SECTION("resizing bigger changes size and capacity") { v.resize(10); REQUIRE(v.size() == 10); REQUIRE(v.capacity() >= 10); } }
Для создания тестовых дублей (mocks/stubs) в проектах без gmock я иногда применял FakeIt или Trompeloeil (для C++14/17). Для интеграционного и системного тестирования часто писал собственные утилиты на основе Boost.Test или использовал скрипты на Python.
Ответ 18+ 🔞
Да ты посмотри, какие у нас тут библиотеки для тестов подъехали — прямо как на параде, блядь! Овердохуища вариантов, глаза разбегаются, ёпта.
Ну, первым делом, конечно, Google Test с Google Mock. Это, можно сказать, мой конёк, когда проект размером с хороший такой особняк. Чувак, там столько всего наворочено — макросы для проверок, фикстуры, тесты с параметрами... А уж моки — это вообще отдельная песня, ядрёна вошь! Прям как по маслу: объявил интерфейс, наклепал мок-класс, прописал ожидания — и сиди, проверяй, как твой код с этим виртуальным говном взаимодействует. Удобно, блядь, до безобразия.
#include <gtest/gtest.h>
#include <gmock/gmock.h>
TEST(CalculatorTest, AddsTwoNumbers) {
EXPECT_EQ(Add(2, 3), 5);
}
class MockDatabase : public DatabaseInterface {
public:
MOCK_METHOD(std::string, FetchName, (int id), (override));
};
TEST(UserTest, GetsUserName) {
MockDatabase db;
EXPECT_CALL(db, FetchName(42))
.WillOnce(Return("John Doe"));
// Тестируемый код, использующий db
}
А вот Catch2 — это уже другая история, более камерная. Header-only, понимаешь? Захотел — взял один файлик, кинул в проект, и всё, можешь тесты писать. Никакой лишней возни с линковкой, ебушки-воробушки! И синтаксис у него такой... как бы сказать... человеческий. BDD-стиль, где SECTION внутри TEST_CASE — смотрится чисто и понятно, не то что эти древние монстры.
#define CATCH_CONFIG_MAIN
#include <catch2/catch_all.hpp>
TEST_CASE("Vector can be sized and resized", "[vector]") {
std::vector<int> v(5);
REQUIRE(v.size() == 5);
REQUIRE(v.capacity() >= 5);
SECTION("resizing bigger changes size and capacity") {
v.resize(10);
REQUIRE(v.size() == 10);
REQUIRE(v.capacity() >= 10);
}
}
Ну а если вдруг проект без gmock, но моки нужны — тут уже в ход идут другие инструменты. FakeIt или Trompeloeil (для свежих стандартов) — тоже ребята ничего, справляются. А для тестов интеграционных, где всё вместе склепать надо, часто приходилось либо на Boost.Test опираться, либо свои костыли на Python пилить. В общем, скучать не приходится, работа кипит, блядь!