Ich habe heute mir halb den Kopf zerbrochen, wie ich bei TurboGears Tests anhand von Daten in einer Datenbank durchführen kann.
Das erste Problem ist eigentlich keines, aber es hat doch lange gedauert, bis ich darauf kam: Wie lade ich Test-Daten in eine separate Test-Datenbank?
Überall stand einfach nur, dass man zum Start der Anwendung benötigte Daten in
websetup.py ablegen sollte. Mein Denkfehler war einfach nur, dass nosetests
die SQL-Einstellungen von test.ini verwendet und nicht von developement.ini.
Logisch! Aber hat bei mir etwas gedauert…
So, musste also einfach in der test.ini den Wert für sqlalchemy.url
anpassen. Voreingestellt ist eine Memory-Datenbank über SQLite. Da ich jedoch
Gebrauch von (MySQL)-spezifischen Enum-Feldern mache, musste ich diese ändern.
Das zweite Problem war die Integration von Sqlalchemy.migrate, welches ich zur
Entwicklung der Datenbank verwende. Zuersteinmal habe ich die Basisklasse für
den Test von Modellen rausgeworfen. Bei jedem Test hätte sich sonst das
Datenbankschema komplett neu aufgebaut, Daten importiert und nach dem Test
wieder die Datenbank zerstört. Und nein, einfach nur alle Modelle zu löschen
geht bei mir nicht so einfach, da es einige zirkuläre Fremdschlüsselbeziehungen
gibt.
Da nosetest verwendet wird, gibt es die Möglichkeit, in einem test-package
für alle Tests verwendete setup und teardown Funktionen bereitzustellen.
Die Setup-Funktion bringt zuerst die Datenbank auf die aktuelle Version und lädt
dann über websetup.py die Testdaten. Die Teardown-Funktion löscht wieder alle
Tabellen und somit alle Daten. Das schöne daran ist, dass dies nur einmal pro
Testreihe erfolgt.
Und falls ich doch zwischen den Tests mal wieder alles neu brauche, reicht ein einfacher Aufruf der restart() Funktion.
Als drittes sollte nun noch in TestController der Aufruf von websetup.py
unterbunden werden. Haben wir ja schon :-)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | """custom unit and functional test suite """ import os from tg import config from paste.deploy import loadapp from paste.script.appinstall import SetupCommand from routes import url_for import migrate.versioning.api from your_tg_app.model import DBSession conf_dir = config.here sqlalchemy_url = config['app_conf']['sqlalchemy.url'] repository = os.path.join(conf_dir, "migration") def setup_package(): """ loads the database fixture in websetup.py """ # get the directory of the config file # setup the database migrate.versioning.api.upgrade(sqlalchemy_url, repository) # setup the data test_file = os.path.join(conf_dir, 'test.ini') cmd = SetupCommand('setup-app') cmd.run([test_file]) def teardown_package(): """ removes all data in the database by downgrading via migrate """ migrate.versioning.api.downgrade(sqlalchemy_url, repository, 0) def restart(): teardown_package() setup_package() class TestController(object): """ Base functional test case for the controllers. The delphi2 application instance (``self.app``) set up in this test case (and descendants) has authentication disabled, so that developers can test the protected areas independently of the :mod:`repoze.who` plugins used initially. This way, authentication can be tested once and separately. Check delphi2.tests.functional.test_authentication for the repoze.who integration tests. This is the officially supported way to test protected areas with repoze.who-testutil (http://code.gustavonarea.net/repoze.who-testutil/). """ application_under_test = 'main_without_authn' def setUp(self): """Method called by nose before running each test""" # Loading the application: conf_dir = config.here wsgiapp = loadapp('config:test.ini#%s' % self.application_under_test, relative_to=conf_dir) self.app = TestApp(wsgiapp) # database setup done with setup_package() def tearDown(self): """Method called by nose after running each test""" # Cleaning up the database: DBSession.rollback() |