Python: модульный код на основе сокетов?
Я пишу клиентский сервер Python, который использует gevent.socket
для связи. Есть ли хорошие способы тестирования работы кода на уровне сокета (например, проверка того, что SSL-соединения с недопустимым сертификатом будут отклонены)? Или проще простого spawn
реального сервера?
Изменить. Я не считаю, что "наивного" издевательства будет достаточно для тестирования компонентов SSL из-за сложных взаимодействий. Я в этом не прав? Или есть лучший способ проверить SSL'd?
Ответы
Ответ 1
Вы можете легко запустить сервер, а затем получить доступ к нему в тестовом примере. Gevent собственный набор тестов делает именно это для тестирования gevent встроенных серверов.
Например:
class SimpleServer(gevent.server.StreamServer):
def handle(self, socket, address):
socket.sendall('hello and goodbye!')
class Test(unittest.TestCase):
def test(self):
server = SimpleServer(('127.0.0.1', 0))
server.start()
client = gevent.socket.create_connection(('127.0.0.1', server.server_port))
response = client.makefile().read()
assert response == 'hello and goodbye!'
server.stop()
Использование 0
для значения порта означает, что сервер будет использовать любой доступный порт. После запуска сервера фактическое значение, выбранное bind
, доступно как атрибут server_port
.
StreamServer
также поддерживает SSL, передает конструктору конструктор keyfile
и certfile
аргументы, и он переносит каждый сокет с помощью SSLObject
, прежде чем передать его обработчику.
Если вы не используете StreamServer
, а ваш сервер основан на Greenlet, то действительно нерестится, это то, что вы должны делать. Не забывайте kill в конце тестового примера.
Запуск сервера и создание зебры - быстрые операции в gevent, намного быстрее, чем создание нового потока или процесса, и вы можете легко создайте новый сервер для каждого тестового примера. Просто не забудьте очистить, как только вам не понадобится сервер.
Я считаю, что нет необходимости издеваться над любым из gevent API, гораздо проще использовать его, так как серверы и клиенты могут с радостью жить в одном процессе.
Ответ 2
Есть другой способ (ИМО лучше): вы должны издеваться над библиотекой, которую используете.
Примером смешного помощника для python является mox.
Вам не нужен набор серверов с допустимым сертификатом, другой с недопустимым сертификатом, без поддержки ssl вообще, те, которые не отвечают на какие-либо пакеты вообще и т.д. Вы можете имитировать свое поведение с помощью "dummy" клиентский сокет. Как это работает с Mox, вы сначала "учите", что он должен ожидать, и как он должен реагировать, а затем вы выполняете свой реальный код на нем, заменяя настоящий gevent.socket на насмешку. Это требует некоторой практики, чтобы понять, но это того стоит.
Ответ 3
Издевательство и stubbing великолепны, но иногда вам нужно перейти на следующий уровень интеграции. Поскольку размножение сервера, даже поддельное, может занять некоторое время, рассмотреть отдельный тестовый набор (назвать их интеграционными тестами) может быть в порядке.
"Протестируйте его так, как вы собираетесь его использовать" - это моя рекомендация, и если вы издеваетесь так сильно, что ваш тест становится тривиальным, это не так полезно (хотя почти любой тест лучше, чем ни один). Если вас беспокоит обращение с плохими сертификатами SSL, обязательно сделайте несколько плохих и напишите тестовое оборудование, на которое вы можете их подать. Если это означает, что нерест сервера, пусть будет так. Может быть, если эти ошибки вам достаточно, это приведет к рефакторингу, который сделает его проверяемым другим способом.