2

私がやりたいこと

正規表現が正しく構築されていることを確認するために、単体テストを作成しようとしています。

# 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を「リロード」する方法:

  1. filetypes_reは新しい設定で評価されますか?
  2. 同じモデルからインポートされた他のすべてのオブジェクトは影響を受けませんか?

リロード後に不安定になったという理由だけでコードを書き直す必要がありますか(つまり、リロード後にテストに合格しないmediamanager.modelsの他のオブジェクトを意味します)?モジュールのリロードに関するいくつかの記事を読みましたが、通常はお勧めできません。

テストを簡単にするために、この正規表現のようなモジュールレベルのオブジェクトを定義するためのより良い方法はありますか?

4

1 に答える 1

0

いくつかの方法があります。私の頭のてっぺんから:

# mediamanager/models.py

import re

from django.conf import settings

def get_filetypes_re(mm_filetypes=settings.MM_FILETYPES):
    filetypes_re = {}
    for key, exts in settings.MM_FILETYPES.items():
    filetypes_re[key] = re.compile(r'({})'.format('|'.join(exts)))
    return filetypes_re 

そしてあなたのテスト:

MM_FILETYPES={'image': ['jpg', 'png', 'gif'],
                        'document': ['pdf', 'txt'],
                        'audio': ['mp3', 'wav']})

def test_filetype_re(self):
    filetypes_re = mediamanager.models.get_filetypes_re(mm_filetypes=MM_FILETYPES)
    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)
于 2012-07-23T19:40:00.633 に答える