15

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?

4 Answers 4

16

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.

Sign up to request clarification or add additional context in comments.

2 Comments

When I do this my TestCase cannot access self.client. Also is it possible to run all test functions inside of TestCase without fiddling with getattr etc?
what I really want is to run the test case under pdb.
3

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.

Comments

1

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.

1 Comment

Sure, but that creates a new test database to run against. How do I run it against the main (non-test) database?
1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.