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, обязательно сделайте несколько плохих и напишите тестовое оборудование, на которое вы можете их подать. Если это означает, что нерест сервера, пусть будет так. Может быть, если эти ошибки вам достаточно, это приведет к рефакторингу, который сделает его проверяемым другим способом.