Модуль модульного тестирования записи в Python

1

Я пишу обертку для ConfigParser в Python, чтобы обеспечить удобный интерфейс для хранения и получения настроек приложения.

Оболочка имеет два метода: read и write, а также набор свойств для разных параметров приложения.

Метод write является всего лишь оболочкой для метода ConfigParser write с добавлением также создания файлового объекта, необходимого для ConfigParser. Это выглядит так:

def write(self):
    f = open(self.path, "w")
    try:
        self.config_parser.write(f)
    finally:
        f.close()

Я хотел бы написать unit test, который утверждает, что этот метод вызывает IOError, если файл не может быть записан, а в другом случае, когда был вызван метод записи парсера конфигурации.

Второй тест довольно прост в обращении с макетным объектом. Но вызов open делает вещи немного сложными. В конце концов, мне нужно создать файл-объект для передачи в парсер конфигурации. Тот факт, что файл действительно будет создан при запуске этого кода, не делает его очень полезным для unit test. Есть ли какая-то стратегия для насмешливого создания файла? Может ли этот фрагмент кода каким-то образом протестировать? Или это слишком просто для тестирования?

Теги:
unit-testing
file-io

3 ответа

6
Лучший ответ

Во-первых, вам действительно не нужно unit test open(), так как довольно разумно предположить, что стандартная библиотека верна.

Далее вы не хотите делать манипуляции с файловой системой, чтобы получить open() для генерации необходимой вам ошибки, потому что тогда вы не тестируете устройство, вы выполняете функциональный/интеграционный тест, включая файловую систему.

Таким образом, вы могли бы заменить open() в глобальном пространстве имен суррогатом, который просто увеличивает значение IOError. Хотя, вероятно, нужно убедиться, что вы вернетесь, если выполнение продолжается.

Но в конце концов, какое значение имеет тест? Там так мало в этом фрагменте кода, что ваша собственная система. Даже замена open() действительно заканчивается тем, что является тестом, в котором говорится: "Работает ли инструкция try и finally в Python?"

Мое предложение? Просто добавьте инструкцию в docstring, которая записывает ваши ожидания. "Вызывает IOError, если файл не может быть записан". Затем двигайтесь дальше. Вы можете добавить unit test позже, если этот метод получит некоторую сложность (и заслуживает тестирования).

  • 0
    На самом деле это не должно быть в строке документации, потому что это ничего не говорит о функции. Из PEP257: «Он предписывает эффект функции или метода в виде команды (« Сделай это »,« Верни это »), а не в качестве описания; например, не пишите« Возвращает путь ... »." В лучшем случае это должно быть «Поднять IOError if ...», но это неправильно, потому что это не ваша функция, которая делает это.
  • 0
    Это не так. Разрешить распространение ошибки без ее перехвата - это «ререйз». Этот метод вызывает IOError если open() вызывает IOError . И хотя я согласен с PEP257, для строк документации есть нечто большее, чем просто вводная фраза. Это определенно нормальное соглашение - помещать любую документацию, которую вы хотите, в строку документации в сочетании со вступительным заявлением. Имея это в виду, вы можете поместить его в качестве комментария, если считаете его только внутренним, или правильно поместить его в строку документации, если считаете его контрактом с пользователем метода. ( задокументированное поведение)
Показать ещё 2 комментария
4

На самом деле, только open может вызывать исключение в вашем коде. Документы для write() ничего не говорят об исключениях. Возможно, только ValueError или что-то для плохого указателя файла (в результате открытого сбоя, что не может быть здесь).

Сделать IOError для открытия легко. Просто создайте файл в другом месте и откройте его для записи. Или вы можете изменить разрешения для него, чтобы у вас не было доступа.

Вы могли бы использовать здесь инструкцию with, и она будет обрабатывать закрытие.

В python 2.5 вам нужна первая строка. В более поздних версиях вам это не нужно.

from __future__ import with_statement # python 2.5 only

def write(self):
    with open(self.path, 'w') as f:
        self.config_parser.write(f)

Метод записи гарантированно вызывается, если open преуспевает и не будет вызываться, если open вызывает IOError. Я не знаю, зачем вам нужен тест, чтобы узнать, вызвана ли запись. В коде говорится, что это так. Не переусердствуйте.;)

  • 0
    1) Я вообще не хочу задействовать файловую систему по причинам, указанным Трэвисом Брэдшоу в своем ответе. 2) Работает ли оператор with в Python 2.4? 3) Возможно, вы правы в том, что этот код делает так мало, что бессмысленно тестировать.
  • 0
    Дело не в том, что это так мало. Это то, что он не делает ничего, что может потерпеть неудачу. В худшем случае он возвращает IOError по причинам, которые не беспокоятся об этой функции (self.path должен знать, что он содержит). ;) Вместо этого вы должны отдельно протестировать config_parser.write () и убедиться, что он работает.
2

Помните, что вам не нужно тестировать работу open() или ConfigParser, они не являются частью вашего кода. Вам просто нужно проверить, что вы используете их правильно. Вы можете обезопасить модуль с помощью своего собственного open(), точно так же, как и для атрибута экземпляра, и можете возвращать макет из него, который поможет вам протестировать.

Однако модульные тесты не являются моим единственным инструментом, и это одна из функций, достаточно простая для анализа и "доказывания" & dagger; что она работает.

& dagger; Менее строго, чем математики, я уверен, но достаточно хорош для меня.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню