Python unittest: как повторно использовать функции TestCase.assert

#python

#python

Вопрос:

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

 class MyTestCase(unittest.TestCase):
    def assertState(state, value):
        if state_dict[state] == value:
            self.assertTrue(True)
        else:
            self.assertTrue(False)
  

Проблема в том, что вызов asserrState в моем экземпляре MyTestCase сообщит assertError вместо сообщения об ошибке объекта результата теста.

Пожалуйста, подскажите, как я могу написать свои собственные функции assert в подклассе unittest.Тестовый набор.

РЕДАКТИРОВАТЬ: Чего я хочу достичь, так это предоставить наш собственный класс MyTestCase в качестве базового класса, который включает в себя больше функций assert с бизнес-логикой в нем. Таким образом, реальные тесты могут просто подклассировать MyTestCase и использовать эти утверждения, не повторяя один и тот же код. Это означает, что я хочу иметь возможность вызывать MyTestCase.assertState в подклассе MyTestCase и по-прежнему сообщать о сбое теста для этого конкретного результата теста. Что-то вроде следующего.

 class ConcreteTestCase(MyTestCase):
    def test_1(self):
        #do something here
        self.assertState("state", "on")
  

Пожалуйста, дайте мне знать, если есть способ сделать это.

Комментарии:

1. Загляните в исходный файл unittest, в нем могут быть некоторые подсказки.

2. Я думаю, что я не сформулировал свой вопрос яснее. То, что я пытаюсь сделать, в основном использует шаблон декоратора, который MyTestCase будет производным от unittest. Класс TestCase, но предоставляющий больше функций assert, таких как assertState. Конкретные тесты будут представлять собой конкретный testcase, который будет подклассом MyTestCase. Это позволит нам добавить больше методов assert, включая нашу собственную бизнес-логику.

Ответ №1:

 class MyTestCase(unittest.TestCase):
  def assertState(self, state, value):
    self.assertEqual(value, self.state_dict[state])

  def test_whatever(self):
    self.assertState(1, 1)
    self.assertState(2, 2)
  

Ответ №2:

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

Вам просто нужно добавить __unittest = True в модуль, где определен класс.

 import unittest

__unittest = True

class MyTestCase(unittest.TestCase):
    def assertState(state, value):
        if state_dict[state] != value:
            standardMsg = 'the state %s does not match %s' % (state, value)
            self.fail(self._formatMessage(msg, standardMsg))
  

Теперь ваш пользовательский метод assert будет вести себя точно так же, как unittest.Тестовые функции, и при сбое не будет отображаться нежелательная трассировка стека.

Работает на Python 2.7

Источник: http://www.gossamer-threads.com/lists/python/python/1014779

Ответ №3:

Прежде всего, вы забыли self параметр. Во-вторых, как вы это запускаете? Если вам действительно нужен объект результата теста, вот как вы это делаете:

 In [1]: import unittest

In [2]: state_dict = {1:2}

In [3]: class MyTestCase(unittest.TestCase):
   ...:         def assertState(self, state, value):
   ...:             if state_dict[state] == value:
   ...:                 self.assertTrue(True)
   ...:         else:
   ...:                 self.assertTrue(False)
   ...:     def runTest(self):
   ...:         self.assertState(1,2)
   ...:         self.assertState(1,1)
   ...: 

In [4]: r = unittest.TestResult()

In [5]: MyTestCase().run(r)

In [6]: r
Out[6]: <unittest.TestResult run=1 errors=0 failures=1>

In [7]: r.errors
Out[7]: []

In [8]: r.failures
Out[8]: 
[(<__main__.MyTestCase testMethod=runTest>,
  'Traceback (most recent call last):n  File "<ipython console>", line 9, in runTestn  File "<ipython console>", line 6, in assertStatenAssertionErrorn')]
  

Комментарии:

1. Привет, letitbee, это близко к тому, что я хочу, но я думаю, что я не сформулировал исходный вопрос лучше. Что я хочу сделать, так это создать подкласс unittest. TestCase как наш собственный базовый класс TestCase, чтобы тестировщик мог писать конкретные тесты, создав подкласс MyTestCase, который предоставит больше функций assert, поэтому подкласс MyTestCase может использовать новые методы assert. Это похоже на шаблон декоратора. Есть ли хороший способ сделать это?

2. В чем, по-видимому, проблема? Я просто объединил MyTestCase с фактическим тестовым примером, чтобы сэкономить время ввода, ничто не мешает вам создавать подклассы столько, сколько вы хотите.