2

The models under test are

class A(models.Model):
    """ model A"""
    name = models.CharField(max_length=50, unique=True)
    slug = AutoSlugField(max_length=265, unique=True, populate_from='name')
    link = models.URLField(blank=True)

    class Meta:
        verbose_name = 'Model A'

    def __unicode__(self):
        return self.name

class B(models.Model):
    """ model B"""
    name = models.CharField(max_length=50, unique=True)
    slug = AutoSlugField(max_length=265, unique=True, populate_from='name')
    link = models.URLField(blank=True)

    class Meta:
        verbose_name = 'Model B'

    def __unicode__(self):
        return self.name

The simple tests for the given models,

class TestA(TestCase):
    """ Test the A model """

    def setUp(self):
        self.name = 'A'
        self.slug = 'a'
        self.object = A.objects.create(name=self.name)

    def test_autoslug_generaton(self):
        """ test automatically generated slug """
        assert self.object.slug == self.slug

    def test_return_correct_name(self):
        """ test the __unicode__() method """
        assert self.object.__unicode__() == self.name

class TestB(TestCase):
    """ Test the A model """

    def setUp(self):
        self.name = 'B'
        self.slug = 'b'
        self.object = B.objects.create(name=self.name)

    def test_autoslug_generaton(self):
        """ test automatically generated slug """
        assert self.object.slug == self.slug

    def test_return_correct_name(self):
        """ test the __unicode__() method """
        assert self.object.__unicode__() == self.name

Here the tests violates DRY as tests are just duplicates with changed models. how do I refactor the tests as it does not violates DRY?

DRY- Dont Repeat Yourself, a software development philosophy which aims at reducing redundancy and code repetition.

Thanks.

  • Duplicate of http://stackoverflow.com/questions/4566910/abstract-test-case-using-python-unittest – rnevius Apr 09 '16 at 12:31

2 Answers2

2

As mentioned in the answer pointed out in @mevius' comment, multiple inheritance is a way to go. Create a Mixin for the repeated test methods, and just implement setUp and tearDown in the actual test classes:

class MixinAB(object):

    def test_autoslug_generaton(self):
        """ test automatically generated slug """
        assert self.object.code == self.slug

    def test_return_correct_name(self):
        """ test the __unicode__() method """
        assert self.object.__unicode__() == self.name


class TestA(MixinAB, TestCase):
    """ Test the A model """

    def setUp(self):
        self.name = 'A'
        self.slug = 'a'
        self.object = A.objects.create(name=self.name)
user2390182
  • 72,016
  • 6
  • 67
  • 89
0

The suggested duplicate and schwobaseggl's answer solve your high level question, but there's possibly another way to do it that I would argue are better for DRY. Currently you have two models that are 99% identical. I expect some of that is for the sake of keeping your question focused, but assuming there's substantial overlap in your "real" models, you've already failed to not repeat yourself. I would suggest considering refactoring A and B to inherit from a base model (see https://docs.djangoproject.com/es/1.9/topics/db/models/#abstract-base-classes). You could then have a test case for the common functionality that is refactored into the base (which could use instances of A or B) and then separate test cases for the unique portions of A and B.

Foon
  • 6,148
  • 11
  • 40
  • 42
  • thank you. I will refactor the models, I never considered inheriting from the models from an abstract model as the real models seems un-identical but some fields that I wrote tests for . since @schwobaseggl answered the question I'm accepting the answer as the question is specifically about test. –  Apr 09 '16 at 12:53