Модульное тестирование исключений в конструкторе Python - PullRequest
11 голосов
/ 15 июня 2009

Я только начинающий в Python и программировании в целом, и у меня есть несколько вопросов о модуле unittest.

У меня есть класс, и в методе __init__ я делаю некоторые утверждения для проверки на плохие аргументы. Я хотел бы создать юнит-тест, который проверяет наличие такого AssertionError при создании новых экземпляров.

В модуле unittest можно проверить (с assertRaises) конкретное исключение, когда вызывается вызываемый объект, но, очевидно, это будет применяться к методам класса. Как правильно запустить такой тест для конструктора?

Я знаю, что могу просто попытаться создать экземпляр класса с неверными аргументами, и unittest сообщит о сбое теста, но это остановится сразу после первого такого исключения, и даже если я смогу обернуть несколько тестов в несколько тестов функции, это просто не кажется элегантным.

Ответы [ 5 ]

17 голосов
/ 15 июня 2009

В модуле unittest можно проверить (с assertRaises) конкретное исключение, когда вызывается вызываемый объект, но, очевидно, это будет применяться к методам класса. Как правильно выполнить такой тест для конструктора?

Конструктор сам по себе вызывается:

self.assertRaises(AssertionError, MyClass, arg1, arg2)

При этом я хочу повторить озабоченность Носкло и С. Лотта по поводу проверки типов аргументов. Кроме того, вам не следует использовать утверждения для проверки аргументов функции: утверждения наиболее полезны в качестве проверок работоспособности, которые не сработают, если что-то не так внутри вашего кода. Кроме того, операторы assert компилируются, когда Python запускается в «оптимизированном» -O режиме. Если функция должна выполнить какую-то проверку своих аргументов, она должна вызвать правильное исключение.

7 голосов
/ 15 июня 2009

Не связывайтесь с assertRaises. Это слишком сложно.

Сделай это

class Test_Init( unittest.TestCase ):
    def test_something( self ):
        try:
            x= Something( "This Should Fail" )
            self.fail( "Didn't raise AssertionError" )
        except AssertionError, e:
            self.assertEquals( "Expected Message", e.message )
            self.assertEquals( args, e.args )

Любое другое исключение будет обычной ошибкой теста.

Кроме того, не связывайтесь с чрезмерной предварительной проверкой ошибок в методе __init__. Если кто-то предоставляет объект неправильного типа, ваш код не будет работать в нормальном ходе событий и вызовет нормальное исключение обычными средствами. Вам не нужно много раз «предварительно проверять» объекты.

2 голосов
/ 09 апреля 2013

Не знаю, помогает ли это, но у меня возникла следующая проблема:

self.assertRaises(Exception, MyFunction())

Проблема в том, что я не просто передавал MyFunction, но и вызывал его, что приводило к сбою и возникновению исключения. Myfunction ожидает аргумент, и я хочу, чтобы он потерпел неудачу, если ничего не передается. Разочаровал меня некоторое время, пока я не понял это:

self.assertRaises(Exception, MyFunction)

Работает как положено.

1 голос
/ 15 июня 2009

Ну, для начала, проверка на плохие аргументы не является хорошей идеей в python. Python динамически строго типизирован по причине.

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

Вместо этого определите хороший API и очень хорошо документируйте его, используя строки документации и текст, и оставляйте ошибки с неверными аргументами автоматически для пользователя.

Пример:

def sum_two_values(value_a, value_b):
    return value_a + value_b

хорошо, этот пример глуп, но если я проверю и утвердлю значение как целое, функция не будет работать с плавающей запятой, строками, списком, ни по какой причине, кроме моей проверки, так зачем проверять сначала? Он автоматически потерпит неудачу с типами, которые не будут работать, так что вам не о чем беспокоиться.

0 голосов
/ 21 сентября 2009

S.Lott ответ неправильный: self.fail() само вызывает исключение, которое затем будет вызвано исключением в следующей строке:

class NetworkConfigTest1(unittest.TestCase):
    def runTest(self):
        try:
            NetworkConfig("192.168.256.0/24")
            self.fail("Exception expected but not thrown")
        except Exception, error:
            printf("Exception caught: %s" % str(error)
            pass

Вывод был «Исключение ожидалось, но не было сгенерировано», но модульный тест не был помечен как сбой, хотя тестируемый код не был написан!

Более правильный способ проверить, вызывает ли метод исключение, - использовать:

self.failUnlessRaises([error], [callable], [arguments to callable])

В моем случае класс, который я тестирую, называется NetworkConfig, и конструктор должен вызвать исключение, если сетевой дескриптор недопустим. И что сработало:

class NetworkConfigTest1(unittest.TestCase):
    def runTest(self):
        self.failUnlessRaises(Exception, NetworkConfig, "192.168.256.0/24")

Работает как нужно и выполняет правильный тест.

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