Как выполнить модульное тестирование метода __init __ () класса python с помощью assertRaises ()? - PullRequest
24 голосов
/ 18 сентября 2008

У меня есть класс:

class MyClass:
def __init__(self, foo):
    if foo != 1:
        raise Error("foo is not equal to 1!")

и модульный тест, который должен убедиться, что неверный аргумент, переданный конструктору, правильно вызывает ошибку:

def testInsufficientArgs(self):
    foo = 0
    self.assertRaises((Error), myClass = MyClass(Error, foo))

Но я получаю ...

NameError: global name 'Error' is not defined

Почему? Где я должен определять этот объект Error? Я думал, что это встроенный тип исключения по умолчанию, нет?

Ответы [ 3 ]

25 голосов
/ 18 сентября 2008

«Ошибка» в этом примере может быть любым объектом исключения. Я думаю, что вы, возможно, читали пример кода, который использовал его в качестве метасинтетического заполнителя для обозначения «Соответствующий класс исключений».

Базовый класс всех исключений называется «Исключением», и большинство его подклассов являются описательными именами типа ошибки, например «OSError», «ValueError», «NameError», «TypeError».

В этом случае соответствующей ошибкой является «ValueError» (значение foo было неправильным, поэтому ValueError). Я бы порекомендовал заменить «Ошибка» на «ValueError» в вашем скрипте.

Вот полная версия кода, который вы пытаетесь написать, я дублирую все, потому что у вас есть странный аргумент ключевого слова в исходном примере, который вы, кажется, смешиваете с назначением, и я использую ' failUnless 'имя функции, потому что это псевдоним функции:

class MyClass:
    def __init__(self, foo):
        if foo != 1:
            raise ValueError("foo is not equal to 1!")

import unittest
class TestFoo(unittest.TestCase):
    def testInsufficientArgs(self):
        foo = 0
        self.failUnlessRaises(ValueError, MyClass, foo)

if __name__ == '__main__':
    unittest.main()

Вывод:

.
----------------------------------------------------------------------
Ran 1 test in 0.007s

OK

В библиотеке юнит-тестов 'unittest' есть ошибка, которую исправляют другие фреймворки для юнит-тестирования. Вы заметите, что невозможно получить доступ к объекту исключения из вызывающего контекста. Если вы хотите это исправить, вам придется переопределить этот метод в подклассе UnitTest:

Это пример использования:

class TestFoo(unittest.TestCase):
    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
        try:
            callableObj(*args, **kwargs)
        except excClass, excObj:
            return excObj # Actually return the exception object
        else:
            if hasattr(excClass,'__name__'): excName = excClass.__name__
            else: excName = str(excClass)
            raise self.failureException, "%s not raised" % excName

    def testInsufficientArgs(self):
        foo = 0
        excObj = self.failUnlessRaises(ValueError, MyClass, foo)
        self.failUnlessEqual(excObj[0], 'foo is not equal to 1!')

Я скопировал функцию failUnlessRaises из unittest.py из python2.5 и немного ее изменил.

5 голосов
/ 18 сентября 2008

Как насчет этого:

class MyClass:
    def __init__(self, foo):
        if foo != 1:
            raise Exception("foo is not equal to 1!")

import unittest

class Tests(unittest.TestCase):
    def testSufficientArgs(self):
        foo = 1
        MyClass(foo)

    def testInsufficientArgs(self):
        foo = 2
        self.assertRaises(Exception, MyClass, foo)

if __name__ == '__main__':
    unittest.main()
1 голос
/ 18 сентября 2008

Я думаю, вы думаете о Исключении с. Замените слово «Ошибка» в вашем описании на «Исключение», и вы должны быть в порядке: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...