Nose: db setup and teardown

In the last post I noted some documentation related to nose and ORM. Well, they did not work for me because my setup was not exactly like others’. Here is what worked for me. In

tests/__init__.py

:

  • I imported
    from pylons import config

    to get the SQLAlchemy engine embedded in pylons’s config variable

  • I imported
    import quickwiki.model as model

    so that I could get hold of my models and metadata

  • I created a class
    TestModel

    inheriting from

    TestCase

    to hold the setup and teardown code

  • In the
    tearDown

    method, I do

    model.metadata.drop_all(bind=engine)

    to destroy all tables

  • In the
    setUp

    method, I call

    tearDown

    to destroy tables if they have not already been cleaned up, and then call

    model.metadata.create_all(bind=engine)

    to create the tables.

Here is the final code:


"""Pylons application test package

When the test runner finds and executes tests within this directory,
this file will be loaded to setup the test environment.

It registers the root directory of the project in sys.path and
pkg_resources, in case the project hasn't been installed with
setuptools. It also initializes the application via websetup (paster
setup-app) with the project's test.ini configuration file.
"""

import os
import sys
from unittest import TestCase

import pkg_resources
import paste.fixture
import paste.script.appinstall
from paste.deploy import loadapp
from routes import url_for

__all__ = ['url_for', 'TestController']

here_dir = os.path.dirname(os.path.abspath(__file__))
conf_dir = os.path.dirname(os.path.dirname(here_dir))

sys.path.insert(0, conf_dir)
pkg_resources.working_set.add_entry(conf_dir)
pkg_resources.require('Paste')
pkg_resources.require('PasteScript')

test_file = os.path.join(conf_dir, 'test.ini')
cmd = paste.script.appinstall.SetupCommand('setup-app')
cmd.run([test_file])

from pylons import config
import quickwiki.model as model

class TestModel(TestCase):
"""
We want the database to be created from scratch before each test and dropped
after each test (thus making them unit tests).
"""

def setUp(self):
self.tearDown()
engine = config['pylons.g'].sa_engine
model.metadata.create_all(bind=engine)

page = model.Page()
page.title = 'FrontPage'
page.content = 'Welcome to the QuickWiki front page'
model.Session.save(page)
model.Session.commit()



def tearDown(self):

engine = config['pylons.g'].sa_engine
model.metadata.drop_all(bind=engine)


class TestController(TestModel):

def __init__(self, *args, **kwargs):
wsgiapp = loadapp('config:test.ini', relative_to=conf_dir)
self.app = paste.fixture.TestApp(wsgiapp)
TestCase.__init__(self, *args, **kwargs)

Well, that almost worked. I fell foul of the ‘setup-app’ command and ‘setup-config’ in websetup.py. As you can see, the ‘tests/__init__.py’ file loads and executes the paster ‘setup-app’ command. Stands to reason: the app should be ‘set up’ before I run tests.

My setup-app is responsible for creating the DB and populating it with some initial data. But now I can’t repeat my tests, because the first time I run the tests, the db is created and initial data put in, and the next time I run the tests… poof:


IntegrityError: (IntegrityError) column title is not unique
u'INSERT INTO pages (title, content) VALUES (?, ?)' ['FrontPage',
'Welcome to the QuickWiki front page']

Well, I thought, I would just drop everything in the db in the tearDown and ensure that tearDown is called before setUp is run. No go. For some reason, it seems, the tearDown() is not working.

Well, it seems I must have at least one test, for the fixtures to be run. So I created a dummy test, and all was well.

Advertisements
Post a comment or leave a trackback: Trackback URL.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: