2009-07-10 5 views
3

Я использую C++ Test от Parasoft для модульного тестирования кода на C++. Я столкнулся со следующей проблемой. У меня есть функция, подобный следующему один (псевдокод):Как выполнить модульное тестирование методов, связанных с вводом файлов?

bool LoadFileToMem(const std::string& rStrFileName) 
{ 
    if(openfile(rStrFileName) == successfull) 
    { 
     if(get_file_size() == successfull) 
     { 
      if(read_entire_file_to_buffer() == successfull) 
      { 
       return true; 
      } 
      return false; 
     } 
     return false; 
    } 
    return false; 
} 

Мои вопросы в данном случае являются:

Должен ли я использовать заглушки для функций файловой системы? Или я должен включать определенные тестовые файлы для тестирования модульных тестов?

В моем случае класс std::fstream используется для ввода файлов.

Есть ли еще предложения? (Лучше всего, если это сделано в C++ Test, но не обязательно).

ответ

3

Для модульной проверки ЭТОЙ функции вы должны использовать заглушки для каждой из вызываемых функций.

Каждая вызванная функция имеет свой собственный блок тестирования модулей, который выполняет эту функцию.

Для read_entire_file_to_buffer() вы хотите, чтобы по крайней мере один тестовый файл, который переполняет буфер, в массовом порядке, чтобы убедиться, что вы не сбой и сжигание, когда они кормят вас историями Нью-Йоркской фондовой биржи вместо 40-символьного конфигурационного файла, который вы ожидая.

+0

Вы правы, но буфер динамически распределяется так, чтобы быть равным размеру файла. Я немного упростил проблему [у меня есть заглушки для выделения памяти, но C++ Test не помогает мне создавать заглушки для методов класса fstream]. – INS

+0

@ Iulian: динамическое распределение может по-прежнему терпеть неудачу (например, если вы запрашиваете 100 ГБ памяти), если вы взаимодействуете с данными, которые вы не контролируете, вы должны проверить, как ваш код обрабатывает данные, которые он не может обрабатывать (не работает ли он изящно или просто падает?). –

+0

@John R Strohm: Это правильно в теории, но во многих случаях это избыток. Я не хочу поддерживать 1000 строк производственного кода + 20 000 строк тестового кода с собственным набором проблем и ошибок. Должен ли я писать тесты для тестового кода? Издевательство над сложной функцией - непростая задача. –

5

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

+0

Да, но, возможно, мы хотим «имитировать» некоторые ошибки, которые не всегда возникают при использовании файлов. Я предполагаю, что иногда некоторые ошибки невозможно имитировать с помощью * реальной * файловой системы. – INS

+1

Если ошибка чтения файла невозможно смоделировать с помощью реальной файловой системы, то либо это очень неясно, либо просто не произойдет, так как вы будете запускать приложение в * реальной * файловой системе. Исключением является то, что вы разрабатываете систему X и хотите протестировать ошибки, характерные для системы Y. Все рассмотренные вещи я бы не * исключил * издевательство над файлом в модульных тестах, но начал бы с тестов с использованием реальных файлов. –

2

Мое предложение:

Создание заглушек для функций, которые будут вызывать эту функцию.

Создайте единичный тест для этой конкретной функции с образцами тестовых файлов.

Создайте тест интеграции без заглушек, чтобы протестировать весь процесс.

0

Как правило, хорошей идеей в модульном тестировании является то, что вы хотите подражать исходным функциям как можно ближе, прикрывая как можно больше кода, который вы тестируете (покрытие кода). Отверстия в сторону, с которыми я не знаком, примером будет то, что вы хотите убедиться, что при условии, что задано неправильное имя файла, и т. Д. Строка 3 в вашем файле:

if (openfile (rStrFileName) == successl)

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

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

1

Я думаю, что вы ищете технику под названием fault injection. Несколько лет назад я видел проект, который заставил бы программы входить в редко протестированные условия ошибки (ошибки разрешения файлов, malloc return 0 и т. Д.). Я просто не могу запомнить его имя. Надеюсь, ссылка на wikipedia поможет вам начать.

+0

Это начало. Надеюсь, мне удастся это сделать в C++ Test – INS

1

Честно говоря, я бы разделил эту функцию на две части.Одна функция читала бы из std::istream, и один открыл бы файл и вернул бы ifstream (возможно, выделенную кучей по умному указателю). Затем вы можете легко выполнить единичный тест сначала, поставив istringstream вместо ifstream, и последний также должен быть простым в тестировании.