5

I'm writing a Django reusable app. It's not a usual app which can be used on its own. It requires other apps to be usable just like django.contrib.admin or django-dajaxice do.

My current project tree looks like this:

django-myapp/
    docs/
        some.rst
        docs.rst
        ...
    myapp/
        static/
            myapp/
                some_js_stuff.js
        templatetags/
            some_file.py
        __init__.py
        base.py
        manager.py
        ...
    unit_tests/
        __init__.py
        test_base.py
        test_manager.py
    functional_tests/
        __init__.py
        functional_tests.py
        urls.py
    README.rst
    LICENSE
    requirements.txt
    requirements-test.txt
    setup.py
    ...

Unit tests are easy - I'm just testing my code so I don't need complete Django environment to run them. Simple ./setup.py test works perfectly.

Functional testing is the tricky part. I would like to use selenium so I need running dev server and this requires whole Django environment. I'm trying to use django.test.LiveServerTestCase but with no success (It looks like there were no urls defined, setting ROOT_URLCONF in settings and urls attribute in class didn't help).

Every piece of documentation I've found, every question on stackoverflow tells about testing Django apps inside Django project. And here is my question: what is the best (and working) way to run functional/integration tests of reusable app without setting up complete Django project?

Patryk Ściborek
  • 1,031
  • 7
  • 8
  • I assume you have a local development version that works fine? `LiveServerTestCase` essentially requires a working dev environment, but it will use a test database and do the standard setup/teardown for each test it runs. It is hard to run functional tests on something that isn't functional. – Nathan Smith Mar 04 '14 at 17:03

1 Answers1

3

As Nathan says its hard to test a unit in a whole stack, without the stack. So you have to have a settings file. Have a look at how the excellent django-debug-toolbar app does it:

It has a Makefile with a test_selenium rule:

test_selenium:
    DJANGO_SELENIUM_TESTS=true DJANGO_SETTINGS_MODULE=tests.settings \
        django-admin.py test tests

And in its tests module it has a bare bones settings.py with the bare necessities:

  • INSTALLED_APPS with the app under test
  • ROOT_URLCONF wich points to the urls.py
  • stuff like MIDDLEWARE_CLASSES that you may skip because you have none.

and a test_integration.py

@skipUnless('DJANGO_SELENIUM_TESTS' in os.environ, "selenium tests not requested")
class DebugToolbarLiveTestCase(LiveServerTestCase):
    ...

Study their setup. Start at the Makefile and dig down making sure you understand why everything is there.

I like that setup because integration/functional tests tend to be dogslow. Understandably, they test the whole stack with all its moving parts. Their Makefile gives an easy way to skip them. If I were to have a reusable app that uses Javascript, I'd have a look at too. Or some other tool to unittest the javascript. Because running the slow integrationtests just to see if the js units work is a pain.

Community
  • 1
  • 1
Chris Wesseling
  • 6,226
  • 2
  • 36
  • 72
  • Thank you @Chris. This is exactly what I was looking for :) I know that I need minimal initialization of Django stack but I didn't know how to do it correctly. I experimented with custom test runner or with setting up stack inside my functional test module but it didn't work. – Patryk Ściborek Mar 05 '14 at 15:29