тестирование приложения urllib2, ответы HTTP загружаются из файлов

1

Мое приложение python делает много HTTP-запросов ко многим URL-адресам, используя urllib2. Я хотел бы построить набор unit test для проверки моего синтаксического анализа и обработки ошибок.

У меня есть каталог, полный тестовых данных, с несколькими файлами, каждый файл, содержащий один ответ HTTP, с заголовками и данными ответа. (с использованием curl -i) В некоторых случаях эти файлы содержат сообщения об ошибках HTTP (необходимые для проверки обработки ошибок)

В идеале я хотел бы создать mock-объект для замены urllib2.urlopen и вернуть объект mock response.

Мне интересно, есть ли простой способ заставить urllib2 загружать HTTP-ответ непосредственно из файла и анализировать эти данные urllib2 для создания соответствующего объекта ответа (как если бы ответ был прочитан с URL-адреса.

Я попытался использовать url, построенный с помощью протокола "file://", однако заголовки ответов HTTP в верхней части файла не были прочитаны и не были правильно проанализированы.

В качестве альтернативы я рассматриваю возможность написания небольшого класса веб-сервера для работы с тестовыми файлами, однако это похоже на немного больше работы, чем хотелось бы. Было бы проще, если бы urllib2 каким-то образом восстановил объект ответа из ответов http, которые я уже сохранил в файлах (без необходимости создавать веб-сервер для их повторного использования)

Любые идеи?

Теги:
urllib2

2 ответа

2

Я думаю, что лучший подход состоит в том, чтобы высмеять подмножество httplib.HTTPConnection (вызовите полученный класс mockcon для конкретности в следующем) и добавьте обработчик, использующий его и подклассифицируя HTTPHandler (использовать в build_opener - - подклассификация означает, что он может заменить HTTPHandler, который используется build_opener по умолчанию):

class MockHTTPHandler(urllib2.HTTPHandler):

    def http_open(self, req):
        return self.do_open(mockcon, req)

Класс mockcon должен предоставлять методы do_open call - несколько могут быть манекенами (т.е. принимать и игнорировать произвольные args и kwds и ничего не делать):

set_debuglevel
_set_tunnel
request

(может интересоваться 2-м аргументом request, поскольку он дает "селекторную" часть URL-адреса).

Метод __init__ mockcon получает хост-часть URL-адреса в качестве первого arg (то есть сначала после self, конечно) и должен игнорировать следующие kwds (используемые для установки тайм-аута).

Метод get_response mockcon (без аргументов, за пределами, конечно, self) должен возвращать объект ответа HTTP - то есть файл-подобный читаемый объект, который также имеет атрибуты .msg, .status, и .reason и метод get_full_url(), чтобы вернуть URL.

Вы можете использовать фактический экземпляр httplib.HTTPResponse для последней роли, но вы должны инициализировать его с помощью одного mock/dummy arg, который имеет аргумент makefile (игнорирует его аргументы и kwds и возвращает все), и сразу после инициализируя его, reset его аргумент .fp должен быть открытым файлом rb, дающим точно байты, которые настоящий HTTP-ответ получит в своем сокете.

Я думаю, что создание полноценного макета для всего вызова urllib2.urlopen может быть проще, чем эта попытка повторного использования большинства функций urllib2httplib, которые он использует внутри), хотя, возможно, и не совсем так же просто, как подход "локального веб-сервера", который, по вашему мнению, больше подходит для работы. Но стоит подумать обо всех трех подходах (макет, безусловно, будет самым легким/быстрым в работе, самый медленный локальный веб-сервер... а также потребует как-то модификации URL-адресов, предварительно назначив им http://localhost:someport/),.

1

Серверный подход определенно не работает, это, вероятно, самая легкая и наименее работающая из всех ваших альтернатив.

Отъезд: http://docs.python.org/library/simplehttpserver.html

7-строчная программа python, которая при запуске из определенного каталога будет обслуживать все файлы (и, рекурсивно, любые файлы в подкаталогах) через HTTP.

Вероятно, вы можете запустить свой unit test код и остановить сервер, поэтому вам не нужно его запускать, даже если он не тестируется.

  • 0
    Несмотря на простоту простых тестов, обычно не очень хороший подход - запускать запущенный сервер (тоже новый процесс) для модульных тестов , насмешек над внешними объектами и функциональностью. Для многих других видов тестирования это хороший вариант. Причина не слишком сильна, чтобы понизить хотя!
  • 0
    Я согласен, правильное решение было бы лучше в целом. Я только отвечал на утверждение, что для этого было бы слишком много работы. С точки зрения быстрого запуска и запуска это, вероятно, самая легкая вещь. Это определенно не лучший в долгосрочной перспективе, я не спорил, что вообще

Ещё вопросы

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