Leopd
Leopd

Reputation: 42769

How do I run a django TestCase manually / against other database?

I have some methods written into a django.test.TestCase object that I'd like to run from the manage.py shell on my real database. But when I try to instantiate the TestCase object to run the test method, I get this error:

ValueError: no such test method in <class 'track.tests.MentionTests'>: runTest

Is there a way to instantiate the TestCase objects? Or is there a way to run a test method against a non-test database?

Upvotes: 15

Views: 5986

Answers (4)

Guido U. Draheim
Guido U. Draheim

Reputation: 3271

The "runTest" problem does usually come up as people do overlook the fact that the unittest.TestCase does have a default argument in its constructor. Have a look at lib/python/unittest/case.py

class TestCase:
    def __init__(self, methodName='runTest'):

Notice that the baseclass "TestCase" does not provide a default implementation of "def runTest" but it does nethertheless try to invoke it. That's where the error comes from. The actual confusion comes from the fact that using "unittest.main()" does not need a runTest method but it will still call all "def test*" functions. This works ... but not because of a default behaviour of TestCase but the inspection code from unittest.main - this is doing something like the following:

class MyTest(unittest.TestCase):
    def test_001(self):
        print "ok"

if __name__ == "__main__":
     suite = unittest.TestSuite()
     for method in dir(MyTest):
         if method.startswith("test"):
             suite.addTest(MyTest(method))
     unittest.TextTestRunner().run(suite)

Answering the original question "I have some methods written into a django.test.TestCase": you need to add each method individually onto a testsuite by using your testclass and providing the target method name as the first argument upon object creation.

Upvotes: 3

TTimo
TTimo

Reputation: 1406

I ran into this, and worked out the following solution:

In your myapp/tests.py, set things up like this:

# get the straight-up Python unittest without the Django machinery                                                                                                                                                                                                                
# NOTE: this is unittest2, a backport of unit testing features from Python 2.7                                                                                                                                                                                                
# (running 2.6 at the time of writing)                                                                                                                                                                                            
from django.utils import unittest
# get the Django wraps                                                                                                                                                                         
from django.test import TestCase as DjangoTestCase

# [..]
# your normal Django unit tests, inheriting from DjangoTestCase
# [..]

class MyTest( unittest.TestCase ):
    def runTest( self ): # NOTE: required name
        self.failUnless( True is True )

def runNonDjangoTests():
    return MyTest() # or unittest.TestSuite( [ MyTest(), .. ] )

You run this test with

~$ unit2 myapp.tests.runNonDjangoTests

For more info, see http://pypi.python.org/pypi/unittest2

This also lets you run unit tests against the main database, with all the potentially destructive side effects. Note that unit2 is pretty dangerous in this context, if you call unit2 myapp.tests it will run all your normal Django tests without staging them to a test database.

Upvotes: 1

Trey Hunner
Trey Hunner

Reputation: 11814

Here's a method that I found recently. I haven't found anything better yet.

from django.test.utils import setup_test_environment
from unittest import TestResult
from my_app.tests import TheTestWeWantToRun

setup_test_environment()
t = TheTestWeWantToRun('test_function_we_want_to_run')
r = TestResult()
t.run(r)
r.testsRun # prints the number of tests that were run (should be 1)
r.errors + r.failures # prints a list of the errors and failures

According to the docs, we should call setup_test_environment() when manually running tests. django.test uses unittest for testing so we can use a TestResult from unittest to capture results when running the test.

In Django 1.2, DjangoTestRunner could be used for more structured testing. I haven't tried this yet though.

Upvotes: 16

Martin Eve
Martin Eve

Reputation: 2751

From the Django testing docs:

Running tests

Once you've written tests, run them using the test subcommand of your project's manage.py utility:

$ ./manage.py test

By default, this will run every test in every application in INSTALLED_APPS. If you only want to run tests for a particular application, add the application name to the command line. For example, if your INSTALLED_APPS contains 'myproject.polls' and 'myproject.animals', you can run the myproject.animals unit tests alone with this command:

$ ./manage.py test animals

Note that we used animals, not myproject.animals. New in Django 1.0: You can now choose which test to run.

You can be even more specific by naming an individual test case. To run a single test case in an application (for example, the AnimalTestCase described in the "Writing unit tests" section), add the name of the test case to the label on the command line:

$ ./manage.py test animals.AnimalTestCase

And it gets even more granular than that! To run a single test method inside a test case, add the name of the test method to the label:

$ ./manage.py test animals.AnimalTestCase.testFluffyAnimals

The last example should be applicable in your case.

If this is what you are doing, you'll need to post a more detailed description of the code employed in your test case.

Upvotes: 1

Related Questions