Модульный тест на С: функции fread / fwrite - PullRequest
1 голос
/ 18 декабря 2011

Я начал писать небольшую программу на C в качестве упражнения для разработки и хочу провести много модульных тестов для этих программ.Проблема в том, что время от времени он использует fread / fwrite и другие стандартные функции - я не хочу, чтобы мои модульные тесты открывали какой-либо файл, поэтому было бы здорово, если бы я мог написать заглушку для fread / fwrite.

У кого-нибудь есть решение этой проблемы?

Заранее спасибо за ответы!

edit: Я забыл одну важную вещь: заглушка для чтения должна вести себя по-разному в разных тестах.В одном возвращаемое значение для чтения должно быть <затем передано число элементов для чтения (имитирует слишком рано eof), а в другом возвращаемое значение для чтения должно быть равно переданному числу элементов для чтения </p>

Ответы [ 4 ]

3 голосов
/ 18 декабря 2011

Есть несколько вариантов:

  1. Превратите fopen(), fread() и т. Д. В косвенные вызовы функций через указатели функций. Для нормальной работы установите для них значение fopen() и т. Д. Для тестирования установите их так, чтобы они указывали на ваши функции.
  2. Определите свои функции замены myfopen(), myfread() и т. Д. Скомпилируйте основную часть программы с помощью макросов с именами fopen, fread и т. Д. И расширением до myfopen, myfread и т. Д.
  3. Определите свои собственные fopen(), fread() и т. Д. Поиграйте с компоновщиком, чтобы он заменил те из стандартной библиотеки. Это очень подвержено ошибкам и трудно сделать.
  4. Hook fopen(), fread() и т. Д. С использованием разборки, сборки и исправления кода во время выполнения. Это тоже не легко.
1 голос
/ 19 декабря 2011

Я могу порекомендовать книгу Эффективно работать с устаревшим кодом , так как она рассматривается в нескольких главах.Я сам использовал его в подобных ситуациях.

Есть две рекомендации для модульного тестирования на процедурных языках (кроме преобразования в объектно-ориентированный язык):

  • Использование компоновщика "шов».Используйте функции-оболочки вокруг вызовов API и компилируйте с различными объектными файлами в зависимости от того, компилируете ли вы тесты или результаты.Тестовая версия блокировала бы вызовы внутри функций-оболочек, тогда как версия для кода выпуска передавала бы вызовы в fread, fwrite и т. Д.
  • Использование «шва предварительной обработки», где вы используете #ifdefs дляизмените поведение либо fread / fwrite / etc, определив локальные версии в специфичном для теста #ifdef, либо добавив немного более поддерживаемый параметр функций-оболочек (опять же), которые изменяют поведение в зависимости от того, определен ли специфичный для теста #ifdef.1010 *
0 голосов
/ 22 сентября 2015

Я бы тоже пошел с макросом.

Создайте файл с:

#define fopen FOPEN
#define fread FREAD
#define fwrite FWRITE

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

Затем вы можете реализовать FOPEN в своем коде заглушки, чтобы делать все, что вы хотите.

0 голосов
/ 18 декабря 2011

Если я правильно понимаю вопрос, самый простой способ сделать это - использовать макрос (пропуская обсуждение его зла):

#ifdef UNIT_TESTS
    #define fwrite(ptr, size, nmemb, stream) (nmemb)
#endif

И то же самое для fread.Теперь вы можете использовать флаг компилятора для указания макроса UNIT_TESTS при компиляции с модульными тестами (например, gcc -DUNIT_TESTS ... для gcc).

...