Тестирование декораторов Python?
Я пишу некоторые модульные тесты для проекта Django, и мне было интересно, возможно ли его (или необходимо?) проверить некоторые из декораторов, которые я написал для него.
Вот пример декоратора, который я написал:
class login_required(object):
def __init__(self, f):
self.f = f
def __call__(self, *args):
request = args[0]
if request.user and request.user.is_authenticated():
return self.f(*args)
return redirect('/login')
Ответы
Ответ 1
Просто:
from nose.tools import assert_equal
from mock import Mock
class TestLoginRequired(object):
def test_no_user(self):
func = Mock()
decorated_func = login_required(func)
request = prepare_request_without_user()
response = decorated_func(request)
assert not func.called
# assert response is redirect
def test_bad_user(self):
func = Mock()
decorated_func = login_required(func)
request = prepare_request_with_non_authenticated_user()
response = decorated_func(request)
assert not func.called
# assert response is redirect
def test_ok(self):
func = Mock(return_value='my response')
decorated_func = login_required(func)
request = prepare_request_with_ok_user()
response = decorated_func(request)
func.assert_called_with(request)
assert_equal(response, 'my response')
Здесь помогает библиотека mock.
Ответ 2
Декоратор, подобный этому, может быть протестирован просто благодаря утиной печати. Просто поставьте макет объекта на функцию вызов, которая, кажется, удерживает и действует как запрос, и посмотрите, получаете ли вы ожидаемое поведение.
Когда нужно использовать модульные тесты, вполне понятно, я бы сказал. В приведенном примере содержится такой базовый код, который можно сказать, что это необязательно. Но опять же, стоимость тестирования такого класса одинаково низкая.
Ответ 3
Пример для Django UnitTest
class TestCaseExample(TestCase):
def test_decorator(self):
request = HttpRequest()
# Set the required properties of your request
function = lambda x: x
decorator = login_required(function)
response = decorator(request)
self.assertRedirects(response)
В общем, подход, который я использовал, следующий:
- Настройте свой запрос.
- Создайте фиктивную функцию, чтобы позволить магии декоратора (lambda). Здесь вы можете контролировать количество аргументов, которые в конечном итоге будут переданы в декоратор.
- Проведите утверждение, основанное на ответе вашего декоратора.