Написание модульных тестов для C/C++ в Visual Studio
С помощью окна Обозреватель тестов вы можете создавать и выполнять модульные тесты для C++. Делается это так же, как и для других языков. Дополнительные сведения об использовании обозревателя тестов см. в разделе Выполнение модульных тестов с помощью обозревателя тестов.
Некоторые функции, такие как Live Unit Testing, закодированные тесты пользовательского интерфейса и IntelliTest, не поддерживаются для C++.
Visual Studio включает в себя эти платформы тестирования C++ без дополнительных загрузок:
- Платформа модульного тестирования Майкрософт для C++
- Google Test
- Boost.Test
- CTest
Вы можете использовать установленные платформы или написать свой собственный адаптер теста для любой платформы, который вы хотите использовать в Visual Studio. Адаптер теста интегрирует компонент модульных тестов с окном Обозреватель тестов. В Visual Studio Marketplace доступно несколько адаптеров сторонних поставщиков. Дополнительные сведения см. в разделе Установка платформ модульного тестирования сторонних поставщиков.
Visual Studio 2017 и более поздних версий (Professional и Enterprise)
Проекты модульных тестов для C++ поддерживают CodeLens.
Visual Studio 2017 и более поздних версий (все выпуски)
- Адаптер Google Test включен по умолчанию в рабочую нагрузку Разработка классических приложений на C++. Он содержит шаблон проекта, который можно добавить в решение. Щелкните правой кнопкой мыши узел решения в Обозревателе решений и выберите Добавить>Новый проект в контекстном меню, чтобы добавить шаблон проекта. Параметры адаптера также можно настроить в окне Сервис>Параметры. Дополнительные сведения см. в статье «Практическое руководство . Использование Google Test в Visual Studio».
- Компонент Boost.Test включен по умолчанию в рабочую нагрузку Разработка классических приложений на C++. Он интегрирован с обозревателем тестов, но в настоящее время не имеет шаблона проекта. Его необходимо настроить вручную. Дополнительные сведения см. в статье «Практическое руководство. Использование Boost.Test в Visual Studio».
- Поддержка CTest включена в компонент Средства CMake C++, который входит в рабочую нагрузку Разработка классических приложений на C++. Дополнительные сведения см. в разделе «Практическое руководство. Использование CTest в Visual Studio».
Более ранние версии Visual Studio
Вы можете скачать расширения «Адаптер Google Test» и «Адаптер Boost.Test» в Visual Studio Marketplace. Найти их можно на страницах Test Adapter for Boost.Test (Адаптер теста для Boost.Test) и Test Adapter for Google Test (Адаптер теста для Google Test).
Базовый процесс тестирования
В следующих разделах описываются основные действия по началу модульного тестирования для C++. Базовая настройка для платформ Майкрософт и Google Test схожа. Boost.Test требует создать тестовый проект вручную.
Создание тестового проекта в Visual Studio 2022
Тесты определяются и выполняются в одном или нескольких тестовых проектах. Тестовый проект создает отдельное приложение, которое вызывает код в исполняемом файле и информирует о его поведении. Проекты создаются в том же решении, что и тестируемый код.
Чтобы добавить новый тестовый проект в существующее решение:
- В Обозревателе решений щелкните правой кнопкой мыши узел решения.
- Во всплывающем меню выберите пункты Добавить>Новый проект.
- Задайте С++ для параметра Язык и введите «тест» в поле поиска. На приведенном ниже рисунке показаны тестовые проекты, доступные при установке рабочей нагрузки Разработка классических приложений на C++ и Разработка для универсальной платформы Windows.

Создание тестового проекта в Visual Studio 2019
Тесты определяются и выполняются в одном или нескольких тестовых проектах. Проекты создаются в том же решении, что и тестируемый код. Чтобы добавить новый тестовый проект в существующее решение:
- В Обозревателе решений щелкните правой кнопкой мыши узел решения.
- Во всплывающем меню выберите пункты Добавить>Новый проект.
- Задайте С++ для параметра Язык и введите «тест» в поле поиска. На приведенном ниже рисунке показаны тестовые проекты, доступные при установке рабочей нагрузки Разработка классических приложений на C++ и Разработка для универсальной платформы Windows.

Создание ссылок на другие проекты в решении
Чтобы обеспечить доступ к функциям в тестируемом проекте, добавьте ссылку на проект в тестовый проект. Щелкните правой кнопкой мыши узел тестового проекта в обозревателе решений. Во всплывающем меню выберите пункты Добавить>Ссылка. В диалоговом окне Добавление ссылки выберите проекты, которые нужно тестировать.

Ссылка на объектный файл или файл библиотеки
Если тестовый код не экспортирует функции, которые требуется протестировать, добавьте выходные OBJ-файлы или LIB-файлы в зависимости тестового проекта. Дополнительные сведения см. в разделе Связывание тестов с объектным файлом или файлом библиотеки. Не включать файлы объектов, имеющие main функцию или другую стандартную точку входа, например wmain , WinMain или DllMain . При добавлении новых исходных файлов в проект обновите зависимости тестового проекта, чтобы включить соответствующие файлы объектов.
Добавление директив #include для файлов заголовков
Далее в CPP-файле модульного теста добавьте директивы #include для всех файлов заголовков, в которых объявляются тестируемые типы и функции. Введите #include » и активирует IntelliSense, чтобы помочь вам выбрать. Повторите эти действия для других заголовков.

Чтобы не вводить полный путь в каждой инструкции include в исходном файле, можно добавить необходимые папки в разделе Проект>Свойства>C/C++>Общие>Дополнительные каталоги включаемых файлов.
Написание методов теста
В этом разделе представлен синтаксис при использовании платформы модульного тестирования Майкрософт для C/C++. Он задокументирован в справочнике по API Microsoft.VisualStudio.TestTools.CppUnitTestFramework. Документацию по Google Test см. на странице Google Test Primer (Начало работы с Google Test). Сведения о Boost.Test см. на странице Boost Test Library: The Unit Test Framework (Библиотека Boost.Test: платформа модульного тестирования).
В CPP-файле в тестовом проекте определены класс-заглушка и метод-заглушка. Они служат примером того, как следует писать код теста. В сигнатурах используются макросы TEST_CLASS и TEST_METHOD, что позволяет обнаруживать методы в окне обозревателя тестов.

TEST_CLASS и TEST_METHOD являются частью собственной платформы тестирования Microsoft. Обозреватель тестов обнаруживает методы теста в других поддерживаемых платформах аналогичным образом.
TEST_METHOD возвращает пустое значение. Чтобы получить результат теста, используйте статические методы класса Assert для сравнения фактических результатов с ожидаемыми. В приведенном ниже примере предполагается, что MyClass имеет конструктор, принимающий std::string . В этом примере показано, как можно проверить, что конструктор инициализирует класс так, как ожидается:
TEST_METHOD(TestClassInit)
В предыдущем примере результат вызова Assert::AreEqual определяет, пройден ли тест успешно. Класс Assert содержит множество других методов для сравнения ожидаемых и фактических результатов.
В методы теста можно добавлять признаки, определяющие владельцев теста, приоритет и другие характеристики. Затем с помощью этих значений можно сортировать и группировать тесты в обозревателе тестов. Дополнительные сведения см. в разделе Выполнение модульных тестов с помощью обозревателя тестов.
Запуск тестов

- В меню Тест выберите пункт Windows>, а затем пункт Обозреватель тестов. На рисунке ниже показан тестовый проект, тесты которого еще не выполнялись.
Примечание. Интеграция CTest с обозревателем тестов пока не доступна. Запустите тесты CTest в главном меню CMake.

Для завершившихся сбоем тестов приводятся подробные сведения, которые могут помочь установить причину. Щелкните неудачный тест правой кнопкой мыши. Во всплывающем меню выберите команду Отладить для пошагового выполнения функции, в которой произошел сбой.
Дополнительные сведения об использовании Обозревателя тестов см. в разделе Выполнение модульных тестов с помощью Обозревателя тестов.
Дополнительные сведения о модульном тестировании см. в статье Основные сведения о модульных тестах.
Использование CodeLens
Visual Studio 2017 и более поздних версий (выпуски Professional и Enterprise)
CodeLens позволяет быстро просмотреть состояние модульного теста, не выходя из редактора кода.
Инициализировать CodeLens для проекта модульного теста C++ можно любым из перечисленных ниже способов.
- Отредактировать и собрать тестовый проект или решение.
- Перестроить проект или решение.
- Запустить тесты из окна обозревателя тестов.
После инициализации значки состояния тестов отобразятся над каждым модульным тестом.
![]()
Щелкните значок для получения дополнительных сведений или выполните или отладите модульный тест:

Связанный контент
Как писать юнит-тесты. Рабочие примеры и подробное руководство
![]()
Прежде чем искать , как написать юнит — тест, нужно определиться, а нужен ли он вашему приложению? Ведь написание unit — тестов — это дополнительные работа и время, поэтому это не всегда эффективно в небольших разработках.
С другой стороны, есть мнение , что сложные разработки лучше начинать с написания тестов, а не с самой программы. И в этом есть свои преимущества, к примеру, в таком случае у вас будет уже готовая структура будущего приложения и вы точно не сделаете спагетти-код в своей будущей разработке.
Если вы определили, что ва м необходимо написание unit — тестов, то относитесь к этому процессу так же серьезно, как и к самой разработке — это сэкономит вам в дальнейшем кучу времени.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Как писать юнит-тесты. Рабочие примеры и подробное руководство
![]()
Прежде чем искать , как написать юнит — тест, нужно определиться, а нужен ли он вашему приложению? Ведь написание unit — тестов — это дополнительные работа и время, поэтому это не всегда эффективно в небольших разработках.
С другой стороны, есть мнение , что сложные разработки лучше начинать с написания тестов, а не с самой программы. И в этом есть свои преимущества, к примеру, в таком случае у вас будет уже готовая структура будущего приложения и вы точно не сделаете спагетти-код в своей будущей разработке.
Если вы определили, что ва м необходимо написание unit — тестов, то относитесь к этому процессу так же серьезно, как и к самой разработке — это сэкономит вам в дальнейшем кучу времени.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Юнит тесты на Си — нет ничего проще
Прочитав статью «Тестирование встроенных систем» и комментарии к ней я был несколько поражен тем фактом, что многие хабровчане знакомы с книгой «Test Driven Development for Embedded C (Pragmatic Programmers)» и framework-ом Unity, но не используют весь арсенал средств, которые предлагают ребята из throwtheswitch.org.
Хочу кратко поделится опытом использования этих самых средств.
О себе
Так получилось, что я нарабатывал свой опыт в программировании встраиваемых систем через тесты (Unit, Integration, System, Stress). За три года мне посчастливилось пройти путь от Junior’a и написания тестов, покрывающих код других специалистов, до Senior’a с опытом разработки систем с использованием TDD методологии.
Обещанное
Упомянутый выше framework Unity очень прост и удобен в использовании. Но это всего лишь вершина айсберга. На странице throwtheswitch.org есть следующие инструменты.
CMock — инструмент позволяющий автоматически генерировать Си-код mock-ов для Ваших тестов. Написан на Ruby. Утверждаю, как человек, который на протяжении трех лет «генерировал» mock-и руками — это просто подарок для Си-разработчика. Но использовать его автономно без следующего инструмента, на мой взгляд, не рационально.
Ceedling — это целая билд-система, как утверждают сами авторы. Но по сути — это все, что Вам нужно для работы. Данный пакет содержит в себе все необходимое: Unity («тест-раннеры» и «чекалки» значений), CMock (генератор моков) и поддержку командной строки через ruby make.
Other — под этим странным заголовком находится очень, полезный, на мой взгляд инструмент — CException. Невероятно маленькая библиотека для Си позволяющая получить некое подобие исключений. Но дезинформировать не буду. В проектах использовать не довелось.
Единственное, что оставляет желать лучшего в этом многообразии прекрасных вещей, так это tutorial. Его, как бы, и нет. Все понятно, но с чего новичку начать — большой вопрос. Попробую исправить ситуацию.
Прежде всего, Ceedling должен быть корректно установлен и проверен на работоспособность как указано тут.
После установки создаем папку и тестовое окружение проекта командой:
ceedling new MyNewProject
- build — сюда будут помещаться все артефакты при сборке и прогоне тестов
- src- это место для нашего «боевого» кода, который подлежит тестированию
- test — будут лежать все наши тесты
- vendor — собственно сам framework, с документацией и плагинами
- project.yml — конфигурационный файл тестового проекта. Позволяет делать хороший тюнинг, но это с опытом
Пора писать первый тест.
Поместим в папку test файл test_calc.c следующего содержания:
#include "unity.h" #include "calc.h" void setUp(void) < >void tearDown(void) < >void test_add( void )
Запускаем тест командой:
ceedling test:test_calc.c
Результат ожидаемый. Тест есть, кода нет. Проект не может быть собран.
Добавляем код.
В папку src помещаем два файла:
#ifndef CALC_H #define CALC_H int calc_add(int a, int b); #endif
#include "calc.h" int calc_add(int a, int b)
Повторяем сборку и попытку прогнать тест:
ceedling test:test_calc.c
Если все сделано правильно, то в консоли должны быть результаты теста:
Test 'test_calc.c' ------------------ Compiling test_calc_runner.c. Compiling test_calc.c. Compiling calc.c. Compiling unity.c. Compiling cmock.c. Linking test_calc.out. Running test_calc.out. ------------------------- OVERALL UNIT TEST SUMMARY ------------------------- TESTED: 1 PASSED: 1 FAILED: 0 IGNORED: 0
Этот короткий пример показывает, что test-runner был сгенерирован и добавлен в сборку автоматически. Его код можно найти в папке build/test/runners.
Попробуем усложнить задачу и предположим, что наш «боевой» файл должен уметь считать только при определенном условии, проверка которого осуществляется в другом программном модуле (например, rules.c). Модифицируем код, для иллюстрации:
#include "calc.h" #include "rules.h" int calc_add(int a, int b) < if (rules_is_addition_allowed()) < return a + b; >return 0; >
Добавим еще один файл в папку src:
#ifndef RULES_H #define RULES_H int rules_is_addition_allowed(void); #endif
Попытка запустить тест будет неудачной, так как нет определения для функции rules_is_addition_allowed().
Самое время воспользоваться CMock.
Изменим тест следующим образом:
#include "unity.h" #include "calc.h" #include "mock_rules.h" void setUp(void) < >void tearDown(void) < >void test_add( void ) < int result = 0; rules_is_addition_allowed_ExpectAndReturn(1); result = calc_add(2,2); TEST_ASSERT_EQUAL_INT( 4, result ); >void test_add_off_nominal( void )
Таким образом, мы получили автоматически сгенерированный mock одним лишь указанием «#include «mock_rules.h». Исходный код данного файла можно найти в директории build/test/mocks. Его изучение даст хорошее представление о том, каким образом можно менять поведение подменяемого модуля.
Оговорочки
1. Я использую данный framework только для тестирования кода на PC. Это диктует определенные правила к архитектуре разрабатываемого ПО. Прогонять юнит тесты на реальном железе смысла не вижу. HAL — он либо работает либо нет и тестируется мануально (мое видение ситуации);
2. Я не использую данный framework для тестирования нескольких потоков. Потокобезопастность данного инструмента мной не исследовалась;
3. Данная статья не учит как правильно писать код и/или тесты, а всего-лишь дает краткое представление об упомянутых выше инструментах разработки.
- Тестирование IT-систем
- TDD