тестирование приложения urllib2, ответы HTTP загружаются из файлов - PullRequest
1 голос
/ 19 июля 2010

Мое приложение на Python отправляет множество http-запросов ко многим URL-адресам, используя urllib2.Я хотел бы создать набор модульных тестов для проверки кода анализа и обработки данных.

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

В идеале я хотел бы создать фиктивный объект для замены urllib2.urlopen и возврата ложного ответаобъект.

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

Я попытался использовать URL-адреса, созданные с использованием протокола "file: //", однако заголовки ответа http в верхней части файла не были прочитаны или проанализированы должным образом.

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

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 19 июля 2010

Я думаю, что лучший подход состоит в том, чтобы смоделировать подмножество 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 - несколько могут бытьпустышки (т.е. принимают и игнорируют произвольные аргументы и аргументы kwds и ничего не делают):

set_debuglevel
_set_tunnel
request

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

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

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

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

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

1 голос
/ 08 августа 2010

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

Выезд: http://docs.python.org/library/simplehttpserver.html

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

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

...