Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

add MongoTestRunner and modify MongoTestCase #538

Closed
wants to merge 1 commit into from

3 participants

@zstumgoren

Hi,
I've added a MongoTestRunner that supports both Mongo and RDBMS backends. I've tested the new runner in the following contexts:

  • without an RDBMS configured in settings.py
  • using sqlite as RDBMS backend
  • using postgres as RDBMS

All tests were conducted with Django 1.4

The commit also adds a Testing section to the MongoEngine Django docs. I'm happy to modify the code or docs as you see fit. Let me know. Thanks!

Serdar Tumgoren

Serdar Tumgoren add MongoTestRunner and modify MongoTestCase
MongoTestRunner now supports both Mongo and RDBMS backends.
Also added Testing section to Django docs.
e6faa21
@rozza

Seems some overlap with MongoEngine/mongoengine#51 - any thoughts on either approach?

@zstumgoren

Hi Ross,
The TestSuiteRunner and TestCase in Pull Request 51 only support a stand-alone Mongo environment.

In other words, they will not allow you to run both Django ORM-backed tests and Mongo tests using the standard python manage.py test syntax.

I started out with such an approach, but because it's so common to have mixed RDBMS + Mongo environments, I decided to build a Test Suite Runner that handles all combinations (RDBMS-only, RDBMS+Mongo, Mongo-only).

Would it make sense to have two Test Runners and associated Test Cases? If so, lig and I could rename our Runner and TestCase classes to better reflect their purposes. For instance, MongoStandaloneTestSuiteRunner and MongoDjangoTestSuiteRunner (I'll admit, those are probably a bit verbose). Thoughts?

@lig

This does not work completely if there is no DATABASES section in the settings at all.

@lig

@zstumgoren please look at my django-testing-utils branch. I've added hybrid classes to let the developer to choose at his own to use or not to use settings.DATABASES and RDBMS at all.

Personally I think that it is enough for all Django/Mongoengine setups.

@zstumgoren

I haven't tested your solution, but it looks like it covers all scenarios. Nicely done. I'm fine using that solution if Ross signs off on it.

@zstumgoren zstumgoren closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 13, 2012
  1. add MongoTestRunner and modify MongoTestCase

    Serdar Tumgoren authored
    MongoTestRunner now supports both Mongo and RDBMS backends.
    Also added Testing section to Django docs.
This page is out of date. Refresh to see the latest.
Showing with 117 additions and 7 deletions.
  1. +44 −2 docs/django.rst
  2. +73 −5 mongoengine/django/tests.py
View
46 docs/django.rst
@@ -19,7 +19,7 @@ attributes that the standard Django :class:`User` model does - so the two are
moderately compatible. Using this backend will allow you to store users in
MongoDB but still use many of the Django authentication infrastucture (such as
the :func:`login_required` decorator and the :func:`authenticate` function). To
-enable the MongoEngine auth backend, add the following to you **settings.py**
+enable the MongoEngine auth backend, add the following to your **settings.py**
file::
AUTHENTICATION_BACKENDS = (
@@ -79,7 +79,7 @@ appended to the filename until the generated filename doesn't exist. The
>>> fs.listdir()
([], [u'hello.txt'])
-All files will be saved and retrieved in GridFS via the :class::`FileDocument`
+All files will be saved and retrieved in GridFS via the :class:`FileDocument`
document, allowing easy access to the files without the GridFSStorage
backend.::
@@ -88,3 +88,45 @@ backend.::
[<FileDocument: FileDocument object>]
.. versionadded:: 0.4
+
+Testing
+=======
+
+MongoEngine provides a :class:`MongoTestCase` class that works similarly to the standard
+Django `TestCase <https://docs.djangoproject.com/en/dev/topics/testing/#django.test.TestCase>`_.
+To use the class, first update your Django project's **settings.py** to specify a default
+Mongo database and the custom :class:`MongoTestRunner`::
+
+ MONGO_DATABASE_NAME = 'my-mongo-db'
+ TEST_RUNNER = 'mongoengine.django.tests.MongoTestRunner'
+
+*MongoTestRunner* extends the standard `Django test runner <https://docs.djangoproject.com/en/dev/topics/testing/#defining-a-test-runner>`_
+by creating a temporary Mongo db during the test run. The above configuration would generate
+a temporary database called *test_my-mongo-db*. This database is dropped at the end of the test run.
+
+In addition, if a relational database is configured in **settings**.py, *MongoTestRunner* invokes the Django test runner's
+standard database `setup <https://docs.djangoproject.com/en/dev/topics/testing/#django.test.simple.DjangoTestSuiteRunner.setup_databases>`_
+and `teardown <https://docs.djangoproject.com/en/dev/topics/testing/#django.test.simple.DjangoTestSuiteRunner.teardown_databases>`_ methods.
+This way, *MongoTestRunner* is able to run both standard Django TestCases and MongoTestCases.
+
+To create a *MongoTestCase*, simply import and subclass it in a standard test file::
+
+ ~ myapp.tests.py ~
+ from mongoengine.django.tests import MongoTestCase
+ from myapp.documents import Person
+
+ class PersonTest(MongoTestCase):
+
+ def setUp(self):
+ person = Person(name='Guido',title='BDFL')
+ person.save()
+
+ def test_person_lookup(self):
+ self.assertEqual(Person.objects.get(title='BDFL').name, 'Guido')
+
+.. note::
+
+ By default, *MongoTestCase* clears all data in collections at the end of each test method.
+
+For more details on testing, refer to the documention for `unittest <http://docs.python.org/library/unittest.html>`_ and
+`Django testing <https://docs.djangoproject.com/en/dev/topics/testing/>`_.
View
78 mongoengine/django/tests.py
@@ -1,21 +1,89 @@
#coding: utf-8
-from django.test import TestCase
from django.conf import settings
+from django.test import TransactionTestCase
+from django.test.simple import DjangoTestSuiteRunner
from mongoengine import connect
+from mongoengine.connection import register_connection, DEFAULT_CONNECTION_NAME
-class MongoTestCase(TestCase):
+class MongoTestRunner(DjangoTestSuiteRunner):
+ """Test runner for Mongo and, optionally, a relational database backend.
+
+ Extends `DjangoTestsuiteRunner's <https://github.com/django/django/blob/master/django/test/simple.py>`_
+ setup_databases and teardown_databases methods. MongoTestRunner always creates a test Mongo db, but
+ only creates a test relational db if an RDBMS has been configured in settings.py.
+
+ Intended for use with MongoTestCase.
+
+ Inspired by `django-mongorunner <https://github.com/xintron/django-mongorunner>`_
+
+ USAGE
+
+ ~ settings.py ~
+
+ MONGO_DATABASE_NAME = 'my-mongo-db'
+ TEST_RUNNER = 'mongoengine.django.tests.MongoTestRunner'
+
+ Once configured, import MongoTestCase in test files and use in same
+ way as standard unittest or Django TestCase.
+
"""
- TestCase class that clear the collection between the tests
+ rdbms = settings.DATABASES['default'].get('NAME','')
+ test_db = 'test_%s' % settings.MONGO_DATABASE_NAME
+
+ def setup_databases(self, **kwargs):
+ """Extends DjangoTestSuiteRunner to setup test mongo db."""
+ # If a relational db is configured, invoke standard Django RDBMS setup
+ if self.rdbms:
+ self.old_config = super(MongoTestRunner, self).setup_databases(**kwargs)
+ register_connection('default', self.test_db)
+ print 'Creating test Mongo database: ' + self.test_db
+ return self.test_db
+
+ def teardown_databases(self, db_name, **kwargs):
+ """Extends DjangoTestSuiteRunner to tear down test mongo db."""
+ # If a RDBMS is configured, invoke standard Django RDBMS teardown
+ if self.rdbms:
+ super(MongoTestRunner, self).teardown_databases(self.old_config, **kwargs)
+ from pymongo import Connection
+ conn = Connection()
+ conn.drop_database(db_name)
+ print 'Dropping test Mongo database: ' + db_name
+
+class MongoTestCase(TransactionTestCase):
+ """TestCase class that clears the test Mongo db collections between tests methods.
+
+ In order to use this class, you must first configure the MongoTestRunner in settings.py
+
+ ~ tests.py ~
+
+ from mongoengine.django.tests import MongoTestCase
+ from myapp.documents import Person
+
+ class FooTest(MongoTestCase):
+
+ def setUp(self):
+ person = Person(name='Guido',title='BDFL')
+ person.save()
+
+ def test_person_lookup(self):
+ self.assertEquals(Person.objects.get(title='BDFL').name, 'Guido')
+
+
"""
- db_name = 'test_%s' % settings.MONGO_DATABASE_NAME
+ test_db = 'test_%s' % settings.MONGO_DATABASE_NAME
+
def __init__(self, methodName='runtest'):
- self.db = connect(self.db_name).get_db()
+ self.db = connect(DEFAULT_CONNECTION_NAME)[self.test_db]
super(MongoTestCase, self).__init__(methodName)
+ def _fixture_setup(self):
+ pass
+
def _post_teardown(self):
super(MongoTestCase, self)._post_teardown()
for collection in self.db.collection_names():
if collection == 'system.indexes':
continue
self.db.drop_collection(collection)
+
Something went wrong with that request. Please try again.