Reputation: 42769
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
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
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
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
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