Вызов метода на основе результата после модульного теста в Python

Как вы вызываете функцию после каждого теста в производном классе Python unittest.TestCase на основе результата теста?

Например, допустим, у нас есть следующий тестовый класс:

import sys
from unittest import TestCase

class TestFeedback(TestCase):
  def msg(self, text):
    sys.stdout.write(text + ' ...')

  def on_fail(self):
    sys.stdout.write(' FAILED!\n')

  def on_success(self):
    sys.stdout.write(' SUCCEEDED!\n')

  def test_something(self):
    self.msg('Testing whether True == 1')
    self.assertTrue(True == 1)

  def test_another(self):
    self.msg('Testing whether None == 0')
    self.assertEqual(None, 0)

Я хотел бы, чтобы методы on_success() или on_fail() вызывались после каждого теста в зависимости от результата теста, например.

>>> unittest.main()
...
Testing whether True == 1 ... SUCCEEDED!
Testing whether None == 0 ... FAILED!
<etc.>

Можно ли это сделать и если да, то как?


person Liam Deacon    schedule 21.05.2015    source источник
comment
В связи с тем, что вы спрашиваете, вы можете передать дополнительный аргумент каждому методу assert, который будет отображаться, если тест не пройден. В общем, вы можете захотеть использовать собственный подкласс unittest.result.TestResult   -  person chepner    schedule 21.05.2015
comment
Ответ ниже решил вашу проблему?   -  person muppetjones    schedule 27.05.2015


Ответы (1)


На данный момент, я не думаю, что вы можете сделать это. Объект TestResult исчезнет до того, как вы перейдете к методу tearDown, который, скорее всего, будет самым простым.

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

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

self.assertEqual(None, 0, 'None is not 0')

Какова ваша конечная цель здесь? Запуск юнит-тестов покажет вам, какие тесты завершились неудачей с информацией о трассировке, поэтому я полагаю, что у вас другая цель.

Изменить:
Хорошо, я думаю, что одним из решений было бы написать свой собственный класс TestCase и переопределить метод __call__ (примечание: я не проверял это):

from unittest import TestCase    
class CustomTestCase(TestCase):
    def __call__(self, *args, **kwds):
        result = self.run(*args, **kwds)
        <do something with result>
        return result

Редактировать 2:
Другое возможное решение... проверьте этот ответ

person muppetjones    schedule 21.05.2015
comment
Спасибо за дельный совет - ваши подозрения относительно альтернативной цели верны. Я надеялся, что у меня будет возможность вызвать метод, скажем, тот, который добавляет результат в пользовательскую таблицу результатов успешных и неудачных тестов, однако, возможно, мне будет проще просто создать отчет, используя что-то вроде HTMLTestRunner... - person Liam Deacon; 22.05.2015
comment
Обычно я предпочитаю пробовать существующее решение, а не изобретать велосипед, но если это простой случай, возможно, вы могли бы использовать собственное TestCase (см. редактирование). - person muppetjones; 22.05.2015
comment
Я принял ваш ответ, так как чувствую, что вы много думали и прикладывали усилия к своему ответу. Еще раз спасибо! - person Liam Deacon; 10.06.2015
comment
Я ценю его! Это действительно решило вашу проблему? - person muppetjones; 11.06.2015
comment
Как оказалось, реализация пользовательского TestCase была самой простой и гибкой (и, следовательно, лучшей ИМХО) — она достигла того, чего я хотел, но мне понравилось второе редактирование, указывающее на сторонние пакеты! - person Liam Deacon; 11.06.2015