У нас есть большое многоплатформенное приложение, написанное на C. (с небольшим, но растущим количеством С++). На протяжении многих лет он эволюционировал со многими функциями, которые можно было бы ожидать в большом приложении C/С++:
-
#ifdef
ад - Большие файлы, из-за которых трудно изолировать тестируемый код.
- Функции, которые являются слишком сложными, легко проверяются
Поскольку этот код предназначен для встроенных устройств, для его работы на фактической цели много накладных расходов. Поэтому мы хотели бы сделать больше наших разработок и тестирования в быстрых циклах в локальной системе. Но мы хотели бы избежать классической стратегии "копировать/вставлять в .c файл в вашей системе, исправлять ошибки, копировать/вставлять назад". Если разработчикам удастся это сделать, мы хотели бы снова создать те же тесты и запустить их автоматически.
Вот наша проблема: для того, чтобы реорганизовать код, который будет более модульным, нам нужно, чтобы он был более проверяемым. Но для того, чтобы ввести автоматические модульные тесты, нам нужно, чтобы он был более модульным.
Одна из проблем заключается в том, что, так как наши файлы настолько велики, у нас может быть функция внутри файла, которая вызывает функцию в том же файле, которую нам нужно заглушить, чтобы создать хороший unit test. Похоже, что это будет проблемой, поскольку наш код становится более модульным, но это далеко не так.
Одна вещь, о которой мы думали, заключалась в том, что тегирование "известно, что проверяемый" содержит комментарии. Затем мы могли бы записать исходные файлы сканирования script для проверяемого кода, скомпилировать его в отдельный файл и связать его с модульными тестами. Мы могли бы медленно вводить модульные тесты, поскольку мы исправляем дефекты и добавляем больше функциональных возможностей.
Однако существует опасение, что сохранение этой схемы (наряду со всеми необходимыми функциями заглушки) станет слишком сложной проблемой, и разработчики перестанут поддерживать модульные тесты. Таким образом, другой подход заключается в использовании инструмента, который автоматически генерирует заглушки для всего кода и связывает файл с этим. (единственный инструмент, который мы нашли, это будет дорогостоящим коммерческим продуктом). Но этот подход, по-видимому, требует, чтобы весь наш код был более модульным, прежде чем мы сможем даже начать, поскольку только внешние вызовы могут быть пропущены.
Лично я предпочел бы, чтобы разработчики думали об их внешних зависимостях и грамотно писали свои собственные заглушки. Но это может быть огромным, чтобы заглушить все зависимости для ужасно заросшего, 10 000 строк файла. Возможно, было бы сложно убедить разработчиков, что им нужно поддерживать заглушки для всех внешних зависимостей, но это правильный способ сделать это? (Еще один аргумент, который я слышал, заключается в том, что разработчик подсистемы должен поддерживать заглушки для своей подсистемы. Но мне интересно, могут ли разработчики "форсировать" писать свои собственные заглушки, чтобы улучшить модульное тестирование?)
#ifdefs
, конечно, добавьте еще одну целую размерность в проблему.
Мы рассмотрели несколько основанных на C/С++ фреймворков unit test, и есть много вариантов, которые выглядят хорошо. Но мы ничего не нашли, чтобы облегчить переход от "hairball кода без единичных тестов" к "единичному тестируемому коду".
Итак, вот мои вопросы всем, кто прошел через это:
- Что является хорошей отправной точкой? Мы идем в правильном направлении, или нам не хватает чего-то очевидного?
- Какие инструменты могут быть полезны для перехода? (предпочтительно свободный/открытый источник, поскольку наш бюджет сейчас примерно равен нулю)
Обратите внимание: наша среда сборки основана на Linux/UNIX, поэтому мы не можем использовать какие-либо инструменты только для Windows.