Как факторизовать тестовые случаи Python с помощью тестов на носу - PullRequest
5 голосов
/ 21 февраля 2011

У меня есть несколько функций на графе f (), g () и h (), которые реализуют разные алгоритмы для одной и той же задачи. Я хотел бы провести модульное тестирование этих функций с использованием инфраструктуры unittest.

Для каждого алгоритма всегда должно быть несколько ограничений (например, пустой граф, граф только с одним узлом и т. Д.). Код для проверки этих общих ограничений не должен дублироваться. Итак, тестовая архитектура, которую я начал проектировать, была следующей:

class AbstractTest(TestCase):
  def test_empty(self):
      result = self.function(make_empty_graph())
      assertTrue(result....) # etc..
  def test_single_node(self):
      ...

Тогда конкретные тесты

class TestF(AbstractTest):
  def setup(self):
      self.function = f
  def test_random(self):
      #specific test for algorithm 'f'

class TestG(AbstractTest):
  def setup(self):
      self.function = g
  def test_complete_graph(self):
      #specific test for algorithm 'g'

... и так далее для каждого алгоритма

К сожалению, при тестировании носа выполняется попытка выполнить каждый тест в AbstractTest, и он не работает, поскольку фактическая функция self.function указана в подклассах. Я попытался установить __test__ = False в случае AbstractTest, но в этом случае тест не выполняется вообще (так как это поле наследуется, я полагаю). Я пытался с абстрактным базовым классом (abc.ABCMeta) без успеха. Я читал о MixIn без какого-либо результата (я не очень уверен в этом).

Я совершенно уверен, что я не единственный, кто пытается факторизовать тестовый код. Как ты это делаешь в Python?

Спасибо.

1 Ответ

2 голосов
/ 21 февраля 2011

Нос собирает классы , которые соответствуют регулярному выражению или являются подклассами unittest.TestCase, поэтому самое простое решение - не делать ни одного из них:

class AlgoMixin(object):
  # Does not end in "Test"; not a subclass of unittest.TestCase.
  # You may prefer "AbstractBase" or something else.

  def test_empty(self):
    result = self.function(make_empty_graph())
    self.assertTrue(result)

class TestF(AlgoMixin, unittest.TestCase):
  function = staticmethod(f)
  # Doesn't need to be in setup, nor be an instance attribute.
  # But doesn't take either self or class parameter, so use staticmethod.

  def test_random(self):
    pass  # Specific test for algorithm 'f'.
...