Django: la meilleure façon de tester un modèle abstrait

j'ai besoin d'écrire quelques tests unitaires pour un modèle de base abstrait, qui fournit certaines fonctionnalités de base qui devraient être utilisées par d'autres applications. Il serait nécessaire de définir un modèle qui en hérite uniquement à des fins d'essai; existe-t-il des moyens élégants/simples de définir ce modèle juste pour le test?

j'ai vu des "hacks" qui rendent cela possible, mais jamais vu un "officiel" dans la documentation de django ou dans d'autres lieux similaires.

18
demandé sur Bernhard Vallant 2010-11-26 03:07:35

8 réponses

je viens de tomber sur cette fonctionnalité moi-même: vous pouvez juste hériter de votre modèle abstrait en tests.py et testez ça comme d'habitude. Quand tu cours manage.py tests', Django crée non seulement une base de données de tests, mais valide aussi et synchronise vos modèles de tests.

Testé avec le tronc Django actuel (version 1.2).

17
répondu maikhoepfel 2018-05-22 20:01:39

je suis tombé sur ce récemment et je voulais le mettre à jour pour les nouvelles versions de Django (1.9 et plus tard) vous pouvez utiliser le schéma create_model au lieu de l'obsolète sql_create_model

from django.db import connection
from django.db.models.base import ModelBase
from django.test import TestCase


class ModelMixinTestCase(TestCase):
    """
    Base class for tests of model mixins. To use, subclass and specify
    the mixin class variable. A model using the mixin will be made
    available in self.model.
    """

    def setUp(self):
        # Create a dummy model which extends the mixin
        self.model = ModelBase('__TestModel__' + self.mixin.__name__, (self.mixin,), {'__module__': self.mixin.__module__})

        # Create the schema for our test model
        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(self.model)

    def tearDown(self):
        # Delete the schema for the test model
        with connection.schema_editor() as schema_editor:
            schema_editor.delete_model(self.model)
7
répondu dylanboxalot 2017-03-12 01:35:36

j'ai la même situation. J'ai fini par utiliser une version de la solution @dylanboxalot. J'ai eu des détails supplémentaires de ici spécifiquement après avoir lu la section "Aperçu de la structure D'essai".

setUp et tearDown méthodes sont appelées à chaque fois qu'un test est à exécuter. Une meilleure solution consiste à lancer la création du modèle "abstrait" Une fois, avant que tous les tests ne soient lancés. Pour ce faire, vous pouvez mettre en œuvre l' setUpClassData et aussi mettre en œuvre les tearDownClass.

class ModelMixinTestCase(TestCase):
    '''
    Base class for tests of model mixins. To use, subclass and specify the
    mixin class variable. A model using the mixin will be made available in
    self.model
    '''
    @classmethod
    def setUpClass(cls):
        # Create a dummy model which extends the mixin
        cls.model = ModelBase('__TestModel__' +
            cls.mixin.__name__, (cls.mixin,),
            {'__module__': cls.mixin.__module__}
        )

        # Create the schema for  our test model
        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(cls.model)
        super(ModelMixinTestCase, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        # Delete the schema for the test model
        with connection.schema_editor() as schema_editor:
            schema_editor.delete_model(cls.model)
        super(ModelMixinTestCase, cls).tearDownClass()

Une possible mise en œuvre peut ressembler à ceci:

class MyModelTestCase(ModelMixinTestCase):
    mixin = MyModel

    def setUp(self):
        # Runs every time a test is run.
        self.model.objects.create(pk=1)

    def test_my_unit(self):
        # a test
        aModel = self.objects.get(pk=1)
        ...

Peut-être ModelMixinTestCase la classe devrait être ajoutée à Django? :P

7
répondu m4rk4l 2017-09-19 09:00:01

je pense que ce que vous cherchez est quelque chose comme ceci.

voici le code complet du lien:

from django.test import TestCase
from django.db import connection
from django.core.management.color import no_style
from django.db.models.base import ModelBase

class ModelMixinTestCase(TestCase):                                         
    """                                                                     
    Base class for tests of model mixins. To use, subclass and specify      
    the mixin class variable. A model using the mixin will be made          
    available in self.model.                                                
    """                                                                     

    def setUp(self):                                                        
        # Create a dummy model which extends the mixin                      
        self.model = ModelBase('__TestModel__'+self.mixin.__name__, (self.mixin,),
            {'__module__': self.mixin.__module__})                          

        # Create the schema for our test model                              
        self._style = no_style()                                            
        sql, _ = connection.creation.sql_create_model(self.model, self._style)

        self._cursor = connection.cursor()                                  
        for statement in sql:                                               
            self._cursor.execute(statement)                                 

    def tearDown(self):                                                     
        # Delete the schema for the test model                              
        sql = connection.creation.sql_destroy_model(self.model, (), self._style)
        for statement in sql:                                               
            self._cursor.execute(statement)                                 
6
répondu simlmx 2016-07-15 13:15:44

mise à Jour pour Django >=2.0

j'ai ajouté quelques vérifications pour aider à résoudre ces problèmes et maintenant il fonctionne parfaitement. J'espère que cela aide les gens

from django.db import connection
from django.db.models.base import ModelBase
from django.db.utils import ProgrammingError
from django.test import TestCase

class AbstractModelMixinTestCase(TestCase):

    '''Base class for tests of model mixins/abstract models.
    To use, subclass and specify the mixin class variable. A model using
    the mixin will be made available in self.model'''

    @classmethod
    def setUpClass(cls):
        # Create a dummy model which extends the mixin. A RuntimeWarning will
        # occur if the model is registered twice

        if not hasattr(cls, 'model'):
            cls.model = ModelBase(
                '__TestModel__' +
                cls.mixin.__name__, (cls.mixin,),
                {'__module__': cls.mixin.__module__}
            )

        # Create the schema for our test model. If the table already exists,
        # will pass
         try:
            with connection.schema_editor() as schema_editor:
                schema_editor.create_model(cls.model)
        except OperationalError:
            pass

        super(AbstractModelMixinTestCase, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        # Delete the schema for the test model. If no table, will pass

        try:
            with connection.schema_editor() as schema_editor:
                schema_editor.delete_model(cls.model)
        except OperationalError:
            pass
        super(AbstractModelMixinTestCase, cls).tearDownClass()

à utiliser, mettre en œuvre de la même manière que ci-dessus:

class MyModelTestCase(AbstractModelMixinTestCase):
    """Test abstract model."""
    mixin = MyModel

    def setUp(self):
        self.model.objects.create(pk=1)

    def test_a_thing(self):
        mod = self.model.objects.get(pk=1)
4
répondu DSynergy 2018-08-10 13:29:50

développez une application d'exemple minimale que vous distribuez avec vos modèles 'abstraits'. Fournir des tests pour l'application exemple pour prouver les modèles abstraits.

2
répondu hash1baby 2010-11-26 01:23:56

j'ai ce problème moi-même et ma solution est sur ce gist django-test-abstrait-modèles

vous pouvez l'utiliser comme ceci:

1 - la sous-classe votre django modèles abstraits

2 - Ecrivez votre cas test comme ceci:

class MyTestCase(AbstractModelTestCase):
    self.models = [MyAbstractModelSubClass, .....]
    # your tests goes here ...

3-Si vous n'avez pas fourni self.models attribut il va rechercher l'application courante pour les modèles dans le chemin myapp.tests.models.*

1
répondu MYaser 2013-11-28 10:33:34

tester une classe abstraite n'est pas très utile, car une classe dérivée peut outrepasser ses méthodes. Les autres applications sont responsables de tester leurs classes en fonction de votre classe abstraite.

-4
répondu Stephen Curial 2010-11-28 04:22:02