3

I'm looking for a way to run a full celery setup during django tests, asked in this other SO question

After thinking about it, I think I could settle for running a unittest (it's more of an integration test) in which I run the test script against the main Django (development) database. Is there a way to write unittests, run them with Nose and do so against the main database? I imagine it would be a matter of telling Nose (or whatever other framework) about the django settings.

I've looked at django-nose but wasn't able to find a way to tell it to use the main DB and not a test one.

Community
  • 1
  • 1
Andres
  • 2,880
  • 4
  • 32
  • 38

2 Answers2

5

I don't know about nose, but here is how to run against and existing db with django (1.6) unit tests.

from django.test.runner import DiscoverRunner
from django.db import transaction

class ExistingDBTestRunner(DiscoverRunner):

    def run_tests(self, test_labels, extra_tests=None, **kwargs):
        self.setup_test_environment()
        suite = self.build_suite(test_labels, extra_tests)
        #old_config = self.setup_databases()
        result = self.run_suite(suite)
        #self.teardown_databases(old_config)
        self.teardown_test_environment()
        return self.suite_result(suite, result)

Then in settings.py

if 'test' in sys.argv:
     TEST_RUNNER = '<?>.ExistingDBTestRunner'
     # alternative db settings?

It will be a little different in older versions of django. Also, you may need to override _fixture_setup and _fixture_teardown in your test cases to pass.

The above code will connect to a preexisting database but since each test is wrapped in a transaction the changes won't be available to other connections (like the celery worker). The easiest way to disable transactions is to subclass from unittest.TestCase instead of django.test.TestCase.

joshua
  • 2,509
  • 17
  • 19
  • joshua, thanks, that's a good start. Two questions. First, where would I drop the test runner code into. Using Django 1.5.1. Any way to get it working on it? https://pypi.python.org/pypi/django-discover-runner seems like it might help, but don't really want to change the way all my tests are run for now, or at least minimize having to re-write old tests, not sure if that's a fair assumption. – Andres Dec 18 '13 at 09:38
  • In Django 1.5 sub class 'django.test.simple.DjangoTestSuiteRunner' and basically do the same thing (remove setup and teardown of test databases). You also might not be able to rely on a savepoint rollback because django doesn't really get this right until 1.6. – joshua Dec 18 '13 at 19:52
  • As you say, it will be hard to integrate existing tests. You could write a new test suite as a management command. Look at this answer: http://stackoverflow.com/a/1648881/426600 – joshua Dec 18 '13 at 20:00
  • so close! I tried implementing it, by installing django-discover-runner and essentially replacing the django 1.6 DiscoverRunner with the one provided by the former. Although it runs without a hitch, it doesn't seem to be writing to the main DB. If I create an object in the tests, drop into pdb, then from another python shell try to retrieve it, it's nowhere to be found. Any ideas? – Andres Dec 18 '13 at 20:26
  • I'm guessing it's because transactions aren't being committed. Are you using TransactionMiddleware? – joshua Dec 18 '13 at 20:36
  • I wasn't. Added it and no dice. – Andres Dec 18 '13 at 20:44
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43455/discussion-between-andres-and-joshua) – Andres Dec 18 '13 at 20:46
0

Have you had a look at django-nose? It seems like it would be the right tool for the job.

David
  • 9,635
  • 5
  • 62
  • 68
  • 1
    Right, I have looked at it. Do you know a way to get django-nose to use the main DB instead of it creating a test DB? – Andres Dec 17 '13 at 17:40
  • have a look into django_nose/runner.py because there is a way to not create db on each run. Maybe you could wire the real db name in the _get_test_db_name() function and use the REUSE_DB env var? – David Dec 17 '13 at 17:59