テスト時に自動で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)
テストモジュールのトップレベルに上のコードを置くと、テスト前にテーブルが自動生成される。
もっといい方法があったら教えてください。