Модульный тест (unit test)
Прошивку обычно проверяют целиком: залили, посмотрели на светодиод. Модульный тест проверяет одну функцию — разбор команды, расчёт CRC, фильтр АЦП — отдельно от остальной программы и от микроконтроллера, за доли секунды и столько раз, сколько нужно.
Обновлено Редакция GAW
Модульный тест (unit test) — автоматическая проверка одной функции или одного модуля программы в отрыве от остального кода. Тест подаёт на вход известные данные и сравнивает результат с ожидаемым; если не совпало, он сообщает, какая проверка провалилась и где. Набор таких тестов запускают после каждого изменения и сразу видят, не сломалось ли что-то.
Как выглядит на C
В фреймворке Unity, который часто используют во встраиваемых проектах, ядро — один файл .c и пара заголовков. Тестовый файл содержит:
setUp()иtearDown()— подготовку и уборку, которые выполняются до и после каждого теста;- функции-тесты с проверками вроде
TEST_ASSERT_EQUAL_HEX16(0x4B37, crc); main(), который вызываетUNITY_BEGIN(), затемRUN_TEST()для каждого теста иUNITY_END().
Исполняемый файл собирается из Unity, тестового файла и проверяемого модуля. Без фреймворка простейшая проверка — стандартный макрос assert.
На компьютере, а не на плате
Руководство Unity прямо говорит, что большинство разработчиков запускают модульные тесты не на целевом железе: там слишком много ограничений по памяти и скорости, нет полного контроля над регистрами, а модульные тесты не заменяют системные. Тесты собирают обычным компилятором для компьютера или запускают в симуляторе с тем же компилятором, что и прошивку. Если тесты всё-таки идут на плате, вывод результатов настраивают макросом UNITY_OUTPUT_CHAR — на UART или через semihosting.
Чтобы это работало, код делят на две части: логику, которая только считает, и тонкий слой работы с регистрами. Логику тестируют на компьютере, а зависимости от периферии подменяют тестовыми двойниками.
Что проверять
Лучшие кандидаты — функции без побочных эффектов: разбор кадров протокола, CRC, фильтры, пересчёт кодов АЦП, конечные автоматы. Эталоны для CRC берут из каталога Грега Кука: для CRC-16/MODBUS контрольное значение строки «123456789» — 0x4B37; проверить свои параметры можно в калькуляторе CRC. Как организовать тесты, сборку и подмену регистров в проекте на AVR и STM32 — в статье о модульном тестировании прошивки.
Частые вопросы
Можно ли запускать модульные тесты прошивки на компьютере?
Да, и авторы Unity советуют именно так: собирать тесты как обычную программу для компьютера или для симулятора. На плате мало памяти, нет полного контроля над регистрами, а тест получается медленнее. Для этого код, который считает и принимает решения, отделяют от кода, который пишет в регистры периферии.
Что тестировать модульными тестами в прошивке?
Всё, что зависит только от входных данных: разбор протоколов и кадров, CRC и контрольные суммы, фильтры и пересчёт отсчётов АЦП в физические величины, конечные автоматы, арифметику с фиксированной точкой. Работу с периферией изолируют за интерфейсом и подменяют тестовыми двойниками.
Где взять ожидаемые значения для теста CRC?
Из каталога параметризованных CRC Грега Кука: для каждого алгоритма там указано значение check — CRC от строки «123456789». Для CRC-16/MODBUS это 0x4B37. Тест вычисляет CRC той же строки и сравнивает с эталоном.
Источники
- ThrowTheSwitch. Unity Test Framework v2.7.0: docs/UnityGettingStartedGuide.md, docs/UnityConfigurationGuide.md, src/unity.h — Unity — фреймворк модульного тестирования на C; ядро — один файл .c и пара заголовков; тестовый файл содержит setUp() и tearDown(), которые выполняются до и после каждого теста; main вызывает UNITY_BEGIN(), RUN_TEST() для каждого теста и UNITY_END(); большинство разработчиков запускают тесты не на целевом железе, а как приложения для компьютера или в симуляторе — на железе слишком много ограничений, нет полного контроля над регистрами, и модульное тестирование не заменяет системное; тест собирается из Unity, тестового файла и проверяемого файла; вывод результатов настраивается макросом UNITY_OUTPUT_CHAR
- ISO/IEC 9899:201x (C11), Committee Draft N1570, April 2011 — разд. 7.2.1.1: макрос assert при ложном выражении выводит сведения о месте вызова и вызывает abort — стандартная проверка без фреймворка
- G. Cook. Catalogue of parametrised CRC algorithms with 16 bits, reveng.sourceforge.io, обновлено 11 декабря 2024 — для каждого алгоритма указано контрольное значение check — CRC строки «123456789»; например CRC-16/MODBUS — 0x4B37; такие эталоны — готовые ожидаемые значения для тестов
Нашли ошибку?
Смотрите также
- Модульное тестирование прошивкиТесты на ПК, Unity, подмена регистров и времени, санитайзеры, тесты на плате
- Тестовый двойникПодмена зависимости модуля в тесте: заглушка, мок, имитация
- Утверждение (assert)Проверка внутреннего условия программы во время работы или при сборке
- CRCЦиклический избыточный код для обнаружения ошибок
- Калькулятор CRCCRC-8, CRC-16, CRC-32, Modbus, блок CRC STM32, код на C
- SemihostingМеханизм Arm для ввода-вывода прошивки через подключённый отладчик