テスト時に自動でcreateTable

TurboGearsのテスト時のDBにはたいていsqlite:///:memory:を使う。余計な環境を気にする必要がないのでこれは便利だと思う。
ただし、毎回テーブルをcreateしなおす必要がある。以下SQLObjectの話。

「tg-admin quickstart -i」で自動生成したregister_model.pyには以下のコードが含まれている。
(追記。「tg-admin quickstart -i -t registration」の間違いでした。registrationは別途インストールです)

def create_registration_tables():
    "Create the appropriate database tables."
    RegistrationPendingUser.createTable(ifNotExists=True)
    RegistrationUserEmailChange.createTable(ifNotExists=True)

# Automatically create the registration tables when TurboGears starts up
turbogears.startup.call_on_startup.append(create_registration_tables)

このやり方が標準的なのかもしれないが、モデルの数が増えてくるとメンテナンスも面倒だ。
そこで、モジュール(以下ではmodel.py)を指定して自動でcreateTableする方法を考えてみた。

最初に、「dir(module)」でクラス一覧を取得できるかと考えたが、モジュール内で「from sqlobject import *」してたりすると、余計なものが色々ついてくる。
そのため、先日覚えたinspectと_astを使うやり方を試した。

project/mypkg/util.py

import inspect, _ast

def get_class_names(module):
    source = inspect.getsource(module)
    ast = compile(source, "dont_care", "exec", _ast.PyCF_ONLY_AST)
    return [ obj.name for obj in ast.body
        if isinstance(obj, _ast.ClassDef) ]

def create_tables(classes):
    for cls in classes:
        if hasattr(cls, "createTable"):
            cls.createTable(ifNotExists=True)

上のget_class_names関数で自作モジュールからクラス名一覧を取得できる。

project/mypkg/tests/test_controllers.py

import turbogears
import mypkg.model
from mypkg.model import *
import mypkg.util as myutil

def create_tables():
    myutil.create_tables([ eval(class_name)
        for class_name in myutil.get_class_names(mypkg.model) ])

turbogears.startup.call_on_startup.append(create_tables)

テストモジュールのトップレベルに上のコードを置くと、テスト前にテーブルが自動生成される。

もっといい方法があったら教えてください。