Тестовые параметры декоратора - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть декоратор, который принимает два параметра callback и onerror, оба должны вызываться как-то так

class mydecorator(object):
    def __init__(self, callback, onerror=None):
        if callable(callback):
            self.callback = callback
        else:
            raise TypeError('Callable expected in "callback" parameter')

        self.onerror = onerror
        if self.onerror and not callable(self.onerror):
            raise TypeError('Callable expected in "onerror" parameter')

    def __call__(self, func):
        return self.__param__call__(func)

    def __param__call__(self, func):
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            try:
                self.callback()
            except MyCustomException as e:
                if self.onerror:
                    self.onerror(e.message, e.data)
                else:
                    raise

            return result 
        return wrapper

Я хотел бы проверить, передал ли я неверный параметр, например, не вызываемый, он должен поднять TypeError

Использование Python unittest Каков наилучший подход для достижения этой цели? Я готов сделать что-то вроде:

def test_non_callable_callback_should_return_type_error(self):
    try:
        @mydecorator('this_is_not_a_callable')
        def my_phony_func():
            pass
    except TypeError:
        # Correctly has raised a TypeError, lets just pass
        pass
    else:
        # It has not raised an TypeError, let's fail
        self.fail('TypeError not raised when a non callable passed to callback')

Это должно быть лучше, не так ли?

1 Ответ

0 голосов
/ 18 сентября 2018

Как прокомментировал Лео К , есть гораздо более простой способ проверить, вызывает ли какой-либо код исключение в тесте, хотя разные библиотеки пишут вещи немного по-разному. В unittest.TestCase вы можете использовать self.assertRaises в качестве менеджера контекста:

def test_non_callable_callback_should_return_type_error(self):
    with self.assertRaises(TypeError):
        @mydecorator('this_is_not_a_callable')
        def my_phony_func():
            pass

На самом деле, вы могли бы упростить вещи еще больше, избавившись от ненужных частей тестируемого кода. Поскольку вы ожидаете, что класс mydecorator вызовет исключение при его вызове (а не при вызове экземпляра функции), вы можете избавиться от фиктивной функции и пропустить синтаксис @decorator все вместе. Метод assertRaises может даже сделать вызов для вас:

def test_non_callable_callback_should_return_type_error(self):
    self.assertraises(TypeError, mydecorator, 'this_is_not_a_callable')
...