2008-09-17 4 views
20

У меня есть класс:Как я могу протестировать метод __init __() класса python с assertRaises()?

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? Я думал, что он был встроен в качестве типа исключения по умолчанию, нет?

ответ

20

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

Базовый элемент всех исключений называется «Исключение», и большинство его подклассов являются описательными именами типа ошибки, например «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 и немного изменил его.

+0

здесь, где вы пошло не так, вот что вы хотели вместо этого, и вот код предназначенный для записи. Вероятно, это лучший ответ, который я когда-либо видел. – LoveMeSomeCode 2013-02-03 03:03:20

+2

self.failUnlessRaises устарел сейчас. Вместо этого используйте self.assertRaises. https://docs.python.org/2/library/unittest.html#deprecated-aliases – dghubble 2014-06-12 07:55:00

1

Я думаю, вы думаете о Exception s. Заменить Ошибка слово в описании с Exception, и вы должны быть хорошо идти :-)

5

Как об этом:

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() 
Смежные вопросы