Как отключить time.sleep() в модульном тестировании Python
Я хочу сделать заглушку, чтобы предотвратить sleep.sleep(..), чтобы спать, чтобы улучшить время выполнения единичного теста.
У меня есть:
import time as orgtime
class time(orgtime):
'''Stub for time.'''
_sleep_speed_factor = 1.0
@staticmethod
def _set_sleep_speed_factor(sleep_speed_factor):
'''Sets sleep speed.'''
time._sleep_speed_factor = sleep_speed_factor
@staticmethod
def sleep(duration):
'''Sleeps or not.'''
print duration * time._sleep_speed_factor
super.sleep(duration * time._sleep_speed_factor)
Тем не менее, я получаю следующую ошибку во второй строке кода выше (определение класса):
TypeError: Error when calling the metaclass bases
module.__init__() takes at most 2 arguments (3 given).
Как исправить ошибку?
Ответы
Ответ 1
Вы можете использовать макет библиотеки в своих тестах.
import time
from mock import patch
class MyTestCase(...):
@patch('time.sleep', return_value=None)
def my_test(self, patched_time_sleep):
time.sleep(666) # Should be instant
Ответ 2
Как насчет:
import time
from time import sleep as originalsleep
def newsleep(seconds):
sleep_speed_factor = 10.0
originalsleep(seconds/sleep_speed_factor)
time.sleep = newsleep
Это работает для меня. Я рассказываю об этом в начале теста, который я хочу ускорить, в конце я вернул исходный сон на всякий случай. Надеюсь, поможет
Ответ 3
использование пакета freezegun может помочь вам в этом.
# fake.py
import functools
from datetime import datetime, timedelta
from unittest import mock
from freezegun import freeze_time
def fake_sleep(func):
freezegun_control = None
def fake_sleep(seconds):
nonlocal freezegun_control
utcnow = datetime.utcnow()
if freezegun_control is not None:
freezegun_control.stop()
freezegun_control = freeze_time(utcnow + timedelta(seconds=seconds))
freezegun_control.start()
@functools.wraps(func)
def wrapper(*args, **kwargs):
with mock.patch('time.sleep', fake_sleep):
rv = func(*args, **kwargs)
if freezegun_control is not None:
freezegun_control.stop()
return rv
return wrapper
# test.py
from fake import fake_sleep
import time
@fake_sleep
def test_sleep():
now = datetime.utcnow()
for sleep_seconds in range(10):
for i in range(1, 10):
time.sleep(sleep_seconds)
assert datetime.utcnow() - now >= timedelta(
seconds=i * sleep_seconds)
- общая демонстрация: см. freezegun README
- pytest demo: функция поддельного сна с функцией Gist
Ответ 4
Принятый ответ остается в силе. Однако, начиная с Python 3.3, unittest.mock является официальной частью стандартной библиотеки Python.
import time
from unittest import TestCase
from unittest.mock import patch
class TestMyCase(TestCase):
@patch('time.sleep', return_value=None)
def test_my_method(self, patched_time_sleep):
time.sleep(60) # Should be instant
# the mock should only be called once
self.assertEqual(1, patched_time_sleep.call_count)
# alternative version using a context manager
def test_my_method_alternative(self):
with patch('time.sleep', return_value=None) as patched_time_sleep:
time.sleep(60) # Should be instant
# the mock should only be called once
self.assertEqual(1, patched_time_sleep.call_count)