Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access Django testserver from Django test

I want to write a unit test that performs HTTP requests directly (instead of using django.test.client.Client).

If you're curious why - it's because I want to test a Thrift-over-HTTP API that I expose from my Django application - and I want to use the Thrift client in the unit test.

The problem is that during tests, the server is not actually being run. When using django.test.client.Client, it will simply call the view functions instead of actually making a HTTP request. (Please correct me if I'm wrong.)

So what would be the best way to force the test framework to start the HTTP server?

I tried writing a bash script that does something like this:

./manage.py testserver --addrport 7000 &
PID=$!
sleep 5
./manage.py test --no-input
kill $PID

But that is messy (and doesn't really work) because 1) I need the sleep (otherwise the test will start before the DB is initialized by the test server) and 2) the test will try to initialize the database again (after the testserver already initialized it).

Any other solutions to this?

Thank you.

like image 221
ibz Avatar asked Jun 18 '09 06:06

ibz


People also ask

What are fixtures in Django test?

fixtures . A fixture is a collection of data that Django knows how to import into a database. The most straightforward way of creating a fixture if you've already got some data is to use the manage.py dumpdata command.

How do I skip a Django test?

Just trick it to always skip with the argument True : @skipIf(True, "I don't want to run this test yet") def test_something(): ... If you are looking to simply not run certain test files, the best way is probably to use fab or other tool and run particular tests.

How do I test coverage in Django?

With Django's Test Runner. If you're using manage.py test , you need to change the way you run it. You need to wrap it with three coverage commands like so: $ coverage erase # Remove any coverage data from previous runs $ coverage run manage.py test # Run the full test suite Creating test database for alias 'default'.. ...


2 Answers

Yup, you're right - it's a problem and there is a bug for it: http://code.djangoproject.com/ticket/2879

Just, you might then encounter multithreaded problems, intentionally ommited: http://code.djangoproject.com/ticket/10117 http://code.djangoproject.com/ticket/4513 http://code.djangoproject.com/ticket/3357

I am frustrated, thus I wrote a library that includes starting live server in separate thread and cleaning it afterwards: http://devel.almad.net/trac/django-sane-testing/ . It also starts Django's server multithreaded by runtime monkeypatching and you can use cherrypy http instead (which is better anyway).

Only problem is it requires you to use nose as test framework (100% backward compatibility with standard unittest, but if you're already using something else...). You can then just use --with-django and --with-djangoliveserver/--with-cherrypyliveserver. No idea how it will work with thrift.

Just beware:

  • Please do not bug Django devs with bugreports, you're on your own
  • Windmill provides same solution, so if you're using windmill, you'll probably have port conflicts
like image 108
Almad Avatar answered Oct 18 '22 23:10

Almad


If you want to test your application using real HTTP requests, then use LiveServerTestCase or StaticLiveServerTestCase, which ships with Django.

In your tests.py file, add code like this:

from django.contrib.staticfiles.testing import StaticLiveServerTestCase

class Example(StaticLiveServerTestCase):
    def test_example(self):
        subprocess.check_call(["curl", self.live_server_url])

And then run the tests by running python manage.py test.

like image 24
Flimm Avatar answered Oct 18 '22 22:10

Flimm