私がやりたいこと
正規表現が正しく構築されていることを確認するために、単体テストを作成しようとしています。
# mediamanager/models.py
import re
from django.conf import settings
filetypes_re = {}
for key, exts in settings.MM_FILETYPES.items():
filetypes_re[key] = re.compile(r'({})'.format('|'.join(exts)))
注:実際、このユニットテストを作成している理由はわかりません。このコードは単純なものではないためです…しかし、それは重要ではありません。
ご覧のとおり、最終的な正規表現は、ユーザーが設定できる変数settings.MM_FILETYPESによって異なります。特定の入力をテストする必要があります。この場合、Djangoはデコレータ@override_settingsを提供します。これは、設定値を一時的にオーバーライドします。
# mediamanager/tests.py
import unittest
from django.test.utils import override_settings
from mediamanager.models import (filetypes_re, …) # import everything we want to test
class ModelsTestCase(unittest.TestCase):
@override_settings(MM_FILETYPES={'image': ['jpg', 'png', 'gif'],
'document': ['pdf', 'txt'],
'audio': ['mp3', 'wav']})
def test_filetype_re(self):
filetypes_re_exp = {'image': '(jpg|png|gif)',
'document': '(pdf|txt)',
'audio': '(mp3|wav)'}
for key, value in filetypes_re_exp.items():
self.assertEqual(value, filetypes_re[key].pattern)
残念ながら、このテストは合格しません。モジュールmediamanager.modelsは、設定がオーバーライドされる前にロードされるため、filetypes_reは古い設定を使用してコンパイルされます。新しい設定を有効にするために(どういうわけか)それをリロードする必要があります。
問題
私はこのようにユニットテストを変更しました:
@override_settings(MM_FILETYPES={'image': ['jpg', 'png', 'gif'],
'document': ['pdf', 'txt'],
'audio': ['mp3', 'wav']})
def test_filetype_re(self):
import mediamanager.models # obtaining module object from sys.modules have the same result
reload(mediamanager.models)
filetypes_re = mediamanager.models.filetypes_re
filetypes_re_exp = {'image': '(jpg|png|gif)',
'document': '(pdf|txt)',
'audio': '(mp3|wav)'}
for key, value in filetypes_re_exp.items():
self.assertEqual(value, filetypes_re[key].pattern)
そして、テストに合格しました。しかし、おそらくmediamanager.modelsモジュールから他のオブジェクトをインポートしたため、このテストケースの他のテストは失敗しました。それらのすべてではなく、2つだけです(これは奇妙です)。編集:それはまったく奇妙ではありません。test_filetyes_reおよびreload()呼び出しの後に実行されるテストにのみ失敗します。
質問
次のような方法でモジュールmediamanager.modelsを「リロード」する方法:
- filetypes_reは新しい設定で評価されますか?
- 同じモデルからインポートされた他のすべてのオブジェクトは影響を受けませんか?
リロード後に不安定になったという理由だけでコードを書き直す必要がありますか(つまり、リロード後にテストに合格しないmediamanager.modelsの他のオブジェクトを意味します)?モジュールのリロードに関するいくつかの記事を読みましたが、通常はお勧めできません。
テストを簡単にするために、この正規表現のようなモジュールレベルのオブジェクトを定義するためのより良い方法はありますか?