image


Программируешь микроконтроллеры? Начитался про TDD или просто устал искать баги и переписывать код заново?

Друг, попробуй тесты.

В данной статье будет показано как интегрировать Ceedling в Eclipse/SW4STM32, чтобы при каждой сборке код проходил через тесты.

Что меня натолкнуло на написание статьи?
Я не смог найти подробной инструкции, а по найденным инструкциям сделать не получалось, ввиду их поверхностного или устаревшего содержаний (например запуск ceedling'a больше не осуществляется командой rake).

Инструкция по интеграции ceedling'a в eclipse от разработчиков весьма скудная а единственная найденная инструкция оказалась платной (это стало последней каплей):
image

Установка


На примере OS Windows, CubeMX и SW4STM32.

Устанавливаем Chocolatey
Открываем PowerShell.exe и выполняем:

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

image

Устанавливаем MinGW
Открываем PowerShell.exe и выполняем:
choco install mingw


Устанавливаем ruby
Открываем PowerShell.exe и выполняем:
choco install ruby


Устанавливаем gem ceedling
Перезапускаем PowerShell!

Открываем PowerShell.exe и выполняем:
gem install ceedling


Проверка работоспособности
Открываем PowerShell.exe и выполняем:

cd /

ceedling new test_ceedling

cd test_ceedling

ceedling test:all

image

Создание проекта


Создадим проект с помощью CubeMX
Создаём проект в CubeMX под toolchain/ide SW4STM32.

Запуск CubeMX производить от имени администратора для создания проекта в директории диска С:/

Application structere -> advanced (иначе сходу не собирается проект).

image

Инициализируем ceedling в проект:

cd /

ceedling new test_ceedling

Создадим в проекте следующие структуру и c./h. файлы, добавим пути в project.yml:

image

Добавим source location & includes
image

image

Создадим новый Builder:

image

Arguments -> test:all

image

Запуск


Создадим ещё одно окно консоли для тестов:

image

Переключим его на отображение результатов Ceedling builder'a:

image

Нажимаем ctrl+B и видим результаты тестов в консоли:

image

Добавим периферию


Зачастую результат выполнения функции зависит от внешних составляющих.

Помимо инструмента для генерации тестов — Unity утилита Ceedling поддерживает CMock — генератор mock-объектов и заглушек.

Представим, что наш калькулятор при вычислении разницы,

a - b

если кнопка нажата, считает её иначе.

b - a

То в этом случае наши тесты могут выглядеть следующим образом:

image

Функция проверки нажатия кнопки была объявлена, но не реализована(не написана).

Нажимаем ctrl+B и видим результаты тестов в консоли:

image

В данном случае мы создали имитацию кнопки, на месте которой может быть UART, SPI, I2C и пр.

Заключение


Теперь при каждой сборке приложения справа в уголке можно будет наблюдать результат выполненных тестов:

image

Комментарии (7)


  1. lingvo
    22.02.2019 11:25

    В данном случае мы создали имитацию кнопки

    Вообще-то в этом-то и заключается основная проблема тестов ПО для МК — вы должны имитировать железо полностью, со всеми сопутствующими эффектами, типа дребезга контактов и т.д. Если писать имитаторы для этого — можно замучаться и поэтому часто железное тестирование предпочитают софтверному.


    Но вот с автоматизацией железного тестирования проблема стоит уже совсем в другой области.


    1. ukt
      22.02.2019 18:12

      Причем на эту самую имитацию тоже нужно написать тест.


      1. lingvo
        22.02.2019 18:52
        +1

        Угу. Причем часто этот тест — это инструкция для людей, а не для процессоров, что многократно усложняет задачу. :)


  1. batman12345
    23.02.2019 11:26

    Я не профессиональный программист. Несколько раз пытался понять, что же такое — тесты, но безуспешно. Из статьи получается, что программист должен вообразить и прописать все возможные и невозможные ошибочные сценарии, но как??? Они же ошибочные, а стал быть, при программировании о них даже не думаешь, а если думаешь, то уже не такие они и ошибочные…


    1. lingvo
      23.02.2019 12:04

      По идее правильные тесты должен писать не тот, кто написал код, а другой человек. Тогда результат обычно превосходит ожидания.


    1. AndreyNagih
      23.02.2019 15:38

      Немного не так. Вы пишете программу, которая должна выдавать требуемый результат, при правильных входных данных. А также, должна коректно обрабатывать ошибочные входные данные.

      Вы пишете тесты с корректными входными данными, в них проверяете что результат требуемый. Также, вы пишете тесты с невалидными входными данными, и в них проверяете, что программа не упала и корректно залогировала ошибку, например.

      Как придумать с какими данными запускать вашу программу? Об это суть есть наука о тестировании ПО. Там придумали ряд методик и подходов, позволяющих с одной стороны покрыть всевозможные граничные случаи, а с другой стороны не наплодить миллион тестов.

      Гарантирует ли это то, что вы покроете все возможные ошибочные сценарии и в продакшене ошибки не произойдет? Конечно же нет. И конечно же всё зависит от вашего опыта.

      Как приблизиться к идеальному результату? Изучать тестирование. Практиковаться в написании тестов. Ну и писать новые тесты на те баги, которые у вас нашлись в продакшене.

      Главная ценность модульных тестов в том, что вы автоматизируете регрессионное тестирование, а это значит, что вы сможете быстрее выкатывать релизы, и не бояться менять существующий код, например для рефакторинга.


  1. helicopter91
    25.02.2019 12:48

    Мне когда-то на тему модульного тестирования для embedded очень понравилась вот эта книга: Test Driven Development for Embedded C by James W. Grenning. В целом, тестировать какие-то инкапсулироавнные модули при наличии нормального HAL вполне возможно. А вот если речь идёт об управлении каким-то физическим процессом в реальном времени, причём алгоритм работает по прерываниям от нескольких разных аппаратных блоков, то тут уже сложнее. Хотя всё-равно можно, например, проверить математику на предмет корректности и каких-нибудь целочисленных переполнений.