Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to factorise python test cases with nosetests

I have several functions on graph f(), g() and h() that implements different algorithms for the same problem. I would like to unit-test these functions using unittest framework.

For each algorithm, several constraints should always be valid (such as empty graph, graph with only one node, and so on). The code for those common constraints checking should not be duplicated. So, the test architecture I started to design was the following:

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

Then the specific test cases

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'

... And so on for each algorithm

Unfortunately, nosetests, tries to execute each test in AbstractTest and it does not work since the actual self.function is specified in subclasses. I tried setting __test__ = False in the AbstractTest Case, but in this case, no test is executed at all (since this field is inherited I suppose). I tried with abstract base class (abc.ABCMeta) without success. I have read about MixIn without any result (I am not really confident with it).

I am quite confident I am not the only one that try to factorize the test code. How do you do that in Python?

Thanks.

like image 934
pierre Avatar asked Nov 06 '22 02:11

pierre


1 Answers

Nose gathers classes that match a regex or are subclasses of unittest.TestCase, so the simplest solution is to do neither of those:

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'.
like image 53
Fred Nurk Avatar answered Nov 09 '22 10:11

Fred Nurk