Почти все, кто пишет автотесты, рано или поздно сталкивается с тем, что тест может зависнуть, по причине того что тестируемый сервер перестал отвечать. При этом у сокета, через который ведется общение, не установлен timeout
. Так происходит, потому что разработчики либы для API-обращений как-то забывают про эту тонкость. Это настоящая головная боль, особенно когда тесты запущены на CI и неясно, что там происходит и когда закончится.
Выход безусловно есть. Н-р в python
’e можно явно указать дефолтное значение socket timeout
’a для всех создаваемых socket
’ов:
import socket
socket.setdefaulttimeout(60)
И вроде бы все здорово, но вас будет ждать жестокое разочарование, если для запросов вы используете либу, работающую через мегапопулярный requests. Потому что там есть такой код: requests/connectionpool.py at 5524472cc76ea00d64181505f1fbb7f93f11cc2b · kennethreitz/requests · GitHub. В двух словах, там может установиться значение socket timeout
в None
(бесконечное время ожидания), переписав дефолтное заданное значение, т.е.:
import socket
socket.setdefaulttimeout(60)
sock = socket.socket()
sock.gettimeout() # -> 60.0
sock.settimeout(None)
sock.gettimeout() # -> None
Победить это можно, сделав monkeypatching
для socket
перед запуском тестов:
import socket
def settimeout():
"""Function to return wrapper over ``socket.socket.set_timeout``."""
def wrapper(self, timeout):
"""Wrapper to prevent ability change default socket timeout to None.
Note:
This is workaround for https://github.com/kennethreitz/requests/blob/5524472cc76ea00d64181505f1fbb7f93f11cc2b/requests/packages/urllib3/connectionpool.py#L381 # noqa
Args:
timeout (int): Seconds of socket timeout.
"""
if self.gettimeout() and timeout is None:
return
settimeout_func(self, timeout)
settimeout_func = socket.socket.settimeout.im_func
wrapper.__doc__ = settimeout_func.__doc__
wrapper.__name__ = settimeout_func.__name__
return wrapper
socket.socket.settimeout = settimeout()
После таких манипуляций, вызов settimeout(None)
не будет перезаписывать установленное вами дефолтное значение, какую бы либу вы не использовали (вряд ли девелоперы либы тоже манкипатчат socket
:)).