Source

django-denormalize / denormalize / tests / common.py

from django import test

import logging
log = logging.getLogger(__name__)

class ModelTestCase(test.TestCase):
    # Source:
    # http://stackoverflow.com/questions/502916/django-how-to-create-a-model
    test_models_app = 'denormalize.tests'
    _test_models_initiated = False

    @classmethod
    def setUpClass(cls, *args, **kwargs):
        if not cls._test_models_initiated:
            cls.create_models_from_app(cls.test_models_app)
            cls._test_models_initiated = True
        super(ModelTestCase, cls).setUpClass(*args, **kwargs)

    @classmethod
    def create_models_from_app(cls, app_name):
        """
        Manually create Models (used only for testing) from the specified string app name.
        Models are loaded from the module "<app_name>.models"
        """
        from django.db import connection, DatabaseError
        from django.db.models.loading import load_app

        app = load_app(app_name)
        from django.core.management import sql
        from django.core.management.color import no_style
        sql = sql.sql_create(app, no_style(), connection)
        cursor = connection.cursor()
        for statement in sql:
            try:
                cursor.execute(statement)
            except DatabaseError, excn:
                log.debug("DatabaseError in statement: %s",
                    statement, exc_info=True)


class CollectionTest(object):
    def setUp(self):
        self.models = self.get_models()
        self.models.create_test_books()
        #book = Book.objects.get(title=u"Cooking for Geeks")
        #m = book._meta
        #import code; _d = dict(); _d.update(globals()); _d.update(locals()); code.interact(local=_d)
        self.objs = self.get_test_instances()

    def get_models(self):
        raise NotImplementedError()

    def get_book(self):
        raise NotImplementedError()

    def test_dump(self):
        bookcol = BookCollection()
        doc = bookcol.dump(self.objs['book'])

        # Basic fields
        self.assertTrue('id' in doc)
        self.assertTrue('title' in doc)
        self.assertFalse('summary' in doc, "The summary was not excluded")
        self.assertTrue('year' in doc)
        self.assertTrue('created' in doc)
        self.assertEqual(doc['id'], self.objs['book'].id)

        # Relational fields
        self.assertTrue('publisher' in doc, doc)
        self.assertEqual(doc['publisher']['name'], u"O'Reilly")
        self.assertTrue('authors' in doc, doc)
        self.assertEqual(len(doc['authors']), 1)
        self.assertTrue('chapter_set' in doc, doc)
        self.assertEqual(len(doc['chapter_set']), 7)

        # Other expectations

        # - Tags are pure strings
        self.assertEqual(doc['tags'], [u'cooking', u'geeks', u'technology'])

        # - ForeignKeys not explicitly followed are included as a pure id
        chapter = doc['chapter_set'][0]
        # TODO: we should probably omit it if it's the relation we just followed
        self.assertTrue('book_id' in chapter,
            "If a FK is not followed, its id will be included")

        # - Author emails are excluded
        author = doc['authors'][0]
        self.assertFalse('email' in author, "The author email was not excluded")

    def test_dump_collection(self):
        bookcol = BookCollection()
        docs = list(bookcol.dump_collection())
        self.assertEqual(len(docs), 2)
        if 'pprint' in os.environ:
            pprint(docs)

    def test_get_related_models(self):
        bookcol = BookCollection()
        deps = bookcol.get_related_models()
        for rel in bookcol.select_related + bookcol.prefetch_related:
            # Difference between the filter name and the path name
            if rel == 'chapter_set':
                rel = 'chapter'
            elif rel == 'category_set':
                rel = 'category'
            self.assertTrue(rel in deps, "Relation {0} not found!".format(rel))
        pprint(deps)
        self.assertIs(deps['publisher']['model']._model, self.models.Publisher)
        self.assertIs(deps['extra_info']['model']._model, self.models.ExtraBookInfo)
        self.assertIs(deps['chapter']['model']._model, self.models.Chapter)
        self.assertIs(deps['authors']['model']._model, self.models.Author)
        self.assertIs(deps['tags']['model']._model, Tag)
        self.assertIs(deps['publisher__links']['model']._model, self.models.PublisherLink)