SQLAlchemy + mypy + pytestの環境を整える
TL;DR
SQLAlchemyは素晴らしいORMですが、django等と違ってテストや、migrationは自分でセットアップする必要があります。
ツールは色々あると思いますが、今回は以下の構成で環境を整えます。また、型があると嬉しいのでmypyでチェックします。
- migration -> alembic
- test -> pytest
実際にやることとしては、以下です。
- テスト環境のセットアップ
UserとPostモデルを作成- テスト
- Migration
Install
好きなツールを使ってください。最近はpoetryを使っています。
pyproject.tomlにmypyのsqlalchemy pluginsを追加します。
以下のようになります。
pyproject.toml
DBのセットアップ
migrationできるようにします。
DBも準備します。postgresqlを使用します。永続化したい場合はvolumeのコメントアウトを解除してください。
docker-compose.yaml
ディレクトリ構成
以下のようなディレクトリ構成を使用します。modelsの中身を分割できるようにしておきます。
1. Test環境のセットアップ
まず、全体で使うもの(DBへのURLの取得、DeclativeMeta、セッション中のクエリのカウントクラス)をmodels/base.pyに置きます。
クエリのカウントはテストで主に使うかと思うので、場所はここじゃないほうがいいかもしれません。
models/base.py
conftest.pyで、テスト用のデータベースとテスト用のセッションを作成するfixtureを書きます。
テストを便利にするため、テスト用のデータベースの設定をコマンドライン上で上書きできるようにします。
- テスト用のデータベースはpytestのsession単位で初期化されます。
- テスト用のセッションはpytestのfunction単位で初期化されます。
また、relationが存在する場合、drop_allがうまくいかないので、SET CONSTRAINTS ALL DEFERRED;で制約を無効にしています。
mysqlの場合はSET FOREIGN_KEY_CHECKS=0;を使ってください。
tests/conftest.py
2. Model作成
Userが複数Postを持っている普通のブログを想定します。
dialect, relationには型推論が効かないので明記する必要があります。あとUUID(as_uuid=True)を設定しないと上手く動かないので現状は機械的につけています。
models/blog.py
3. Test
以下のような感じでテストできます。詳細が見たい場合は--echoとかつけるといいです。
tests/test_blog.py
一応DBの中身を確認しておきます。
4. Migration
テストがうまくいったのでmigrationしてmain DBに反映します。
alembicで生成されたmigrations/env.pyを編集します。
Baseを継承したモデルをすべてimportする必要があります
migrations/env.py
alembicでmigrationします。
DBに結果が反映されているかを確認します。
終わりに
以上で個人的に使いやすいSQLAlchemyのテスト環境のセットアップは終わりです。 こうすればもっとよくなる!みたいなものがあれば以下のレポジトリのissueとかで教えてくれると助かります。