Создание тестируемого кода
У меня есть файл - в большой устаревшей кодовой базе - содержащий методы доступа к базам данных. Классы не используются, только заголовочный файл с объявлениями метода и исходный файл с реализацией.
Я хочу переопределить эти методы, чтобы исключить доступ к БД во время модульного тестирования.
Я подумал о следующих вариантах:
- Превратите файл в класс и переопределите методы.
Основным минусом здесь является то, что это приводит к множеству изменений по всей кодовой базе.
Не идеально, хотя это улучшает код... - Оберните весь исходный файл
#ifdef PRODUCTION_CODE
и создайте новый исходный файл, содержащий заглушку, и оберните его противоположным, то есть сделайте все, что зависит от компиляции. Проблема здесь в том, что в системе сборки, которая выполняет регрессионные тесты, мне пришлось бы компилировать дважды, один раз, чтобы создавать приложения и делать регрессионные тесты, и дополнительное время для создания исполняемых файлов модульного теста.
Любые рекомендуемые способы сделать это?
4 ответа
Как насчет того, чтобы взять существующие функции, переместить код внутри нового класса и вызвать новые методы из существующих функций, а затем переопределить этот класс во время тестов?
Вот так:
static DBAccessClass dac = new DBAccessClass ();
void origFunction() { dac.origFunction(); }
И в тесте:
dac = new DBAccessMockup();
Вы можете попробовать переопределить на уровне компоновщика. Имеют два разных файла.cpp, которые реализуют функции в заголовке, который описывает интерфейс БД - один вызывает реальную БД, а другой - фальшивый интерфейс. Когда вы ссылаетесь на модульное тестирование, замените одно на другое (могут помочь переменные, специфичные для целевых объектов в GNU make).
- Превратите файл в класс и переопределите методы. [...]
- Оберните весь исходный файл с помощью #ifdef [...]
Если возможно, перейдите к 1, так как у вас будет централизованный способ обращения к коду базы данных (указатель класса вместо X-функций). Это означает модульность, простоту замены реализации (с заглушками или с другим внутренним компонентом БД) и более инкапсулированный код.
Если вы идете с 2, рассмотрите возможность замены реализации функций. То есть внутри исходных функций задействуйте код тестирования (основанный на if
).
Ваш протестированный код абсолютно независим от того, работает ли он в тестовой среде или нет, потеря производительности незначительна (if(booleanFlagHere)
это незначительная стоимость в большинстве случаев) и вам не нужно изменять проверенный код вообще).
Вы также можете посмотреть книгу Майкла Фезерса " Эффективная работа с устаревшим кодом". Он не только обсуждает именно эти типы проблем, но и включает в себя множество примеров на C++ (в дополнение к Java, C и C#). Перья также является первоначальным создателем CppUnit.