Subscribed unsubscribe Subscribe Subscribe

Djangoの抽象モデル(Abstract Model)の単体テスト

DjangoでAbstractなモデルの単体テストってどう書くんだろうなって思って調べたときのメモ。

継承した先のモデルをテストすればいいとかあるかもしれないけど、抽象モデルなので実装を持つ事ができる。その実装を独立してテストしたいなぁと思った。

簡単な例を書く。こんな論理削除用の抽象モデルがあったとする。

class BaseModel(models.Model):

    del_flg = models.BooleanField(u'削除フラグ', default=False)

    def remove(self):
        self.del_flg = True
        self.save()

    def unremove(self):
        self.del_flg = False
        self.save()

    class Meta(models.Model):
        abstract = True

この場合、remove, unremove が意図した通りに動くかテストしたい。
それをやる時は以下のようなコードを書く。

from django.test import TestCase
from django.db import connection
from django.core.management.color import no_style

class BaseModelTest(TestCase):

    def _getTargetClass(self):
        from core.models import BaseModel # <= 上のヤツ
        from django.db import models

        class BaseDummy(BaseModel):
            pass

        return BaseDummy

    def _makeOne(self, *args, **kw):
        return self._getTargetClass().objects.create(*args, **kw)

    def setUp(self):
        self._style = no_style()
        sql, _ = connection.creation.sql_create_model(self._getTargetClass(), self._style)
        self._cursor = connection.cursor()
        for statement in sql:
            self._cursor.execute(statement)

    def tearDown(self):
        sql = connection.creation.sql_destroy_model(self._getTargetClass(), (), self._style)
        for statement in sql:
            self._cursor.execute(statement)

    def test_remove_unremove(self):
        base_dummy = self._makeOne()

        self.assertTrue(hasattr(base_dummy, 'del_flg'))
        self.assertEqual(base_dummy.del_flg, 0)

        base_dummy.remove()
        self.assertEqual(base_dummy.del_flg, 1)

        base_dummy.unremove()
        self.assertEqual(base_dummy.del_flg, 0)

簡単に説明すると

1. setUpで抽象モデル(BaseModel)を継承したBaseDummyモデル作成
2. BaseDummyのモデル定義から吐き出されるモデル生成用のSQLを取得(sql_create_model)
3. そのSQLを実行してDBにBaseDummyモデルのテーブルを作成
4. テスト実行
5. tearDownでモデル定義から吐き出される削除用のSQLを取得(sql_destroy_model)
6. そのSQLを実行してDBからBaseDummyモデルのテーブルを削除

て事をやってる。なんか面倒だけど、アドホックにこんな感じの事もできるんだなと思った。

こんな欲求に直面したとき、他の人たちはどんな風にしてるだろうかとふと気になった。

おわりん

参考