web-dev-qa-db-ja.com

djangoでFileFieldをユニットテストするきれいな方法は何ですか?

FileFieldを持つモデルがあります。単体テストしたい。 Djangoテストフレームワークには、データベースと電子メールを管理する優れた方法があります。FileFieldsにも同様のものはありますか?

ユニットテストが実際のアプリケーションを汚染しないことを確認するにはどうすればよいですか?

前もって感謝します

PS:私の質問はほぼ テストフィクスチャを使用したDjangoテストFileField の複製ですが、承認された回答がありません。このトピックについて何か新しいことがあれば、もう一度質問してください。

51
luc

これに対処する方法はいくつかありますが、単体テストは分離されているはずなのでファイルはすべて永続的な変更に関するものなので、すべて醜いです。

私の単体テストは本番データのあるシステムでは実行されないので、各実行後に_git reset --hard_のようなものでアップロードディレクトリをリセットするのは簡単です。このアプローチは、コードの変更を含まず、優れたテストデータで作業を開始する限り機能することが保証されているという理由で、いくつかの点で最良です。

モデルのsaveメソッドをテストした後、実際にそのファイルで何もする必要がない場合は、pythonの優れた Mock library を使用してFileインスタンス(つまり、何か)を完全に偽造することをお勧めしますmock_file = Mock(spec=Django.core.files.File); mock_file.read.return_value = "fake file contents")のように、ファイル処理ロジックへの変更を完全に回避できます。 Mockライブラリには、テストメソッド内で globally patch Djangoの File class を実行する方法がいくつかあります。

実際のファイルが必要な場合(つまり、テストの一部として使用する場合、外部スクリプトで処理する場合など)、Mirkoの例に似たものを使用して、確認後に Fileオブジェクト を作成できます。適切な場所に保存されます-これを行う3つの方法を次に示します。

  • テストで_settings.MEDIA_ROOT_が一時ディレクトリを指すようにします(Python tempfile モジュールのmkdtemp関数を参照)。これは、ソースコードの一部であるメディアファイルに使用する別の_STATIC_ROOT_のようなものがあります。
  • カスタムを使用 ストレージマネージャー
  • 各Fileインスタンスでファイルパスを手動で設定するか、カスタムの pload_to 関数を使用して、テストセットアップ/ティアダウンプロセスがパージする場所(_MEDIA_ROOT_の下のテストサブディレクトリなど)を指定します。

編集:モックオブジェクトライブラリがpythonバージョン3.3で新しく追加されました。古いpython =バージョンチェック Michael Foordのバージョン

39
Chris Adams

Djangoはこれを行うための優れた方法を提供します-SimpleUploadedFileを使用します。

from Django.core.files.uploadedfile import SimpleUploadedFile

my_model.file_field = SimpleUploadedFile('best_file_eva.txt', 'these are the file contents!')

これは、Djangoの魔法の機能の1つです。ただし、それは here と呼ばれます。

83
waterproof

私は通常、doctestを使用してモデルのファイルフィールドをテストします

>>> from Django.core.files import File
>>> s = SimpleModel()
>>> s.audio_file = File(open("media/testfiles/testaudio.wav"))
>>> s.save()
>>> ...
>>> s.delete()

必要な場合は、テストクライアントでファイルのアップロードもテストします。

フィクスチャについては、フィクスチャのパスを変更した後、必要なファイルをテストフォルダーにコピーするだけです。

例えば.

「audio」という名前のディレクトリを指すファイルフィールドを持つモデルを含むフィクスチャでは、「audio」:「audio/audio.wav」を「audio」:「audio/test/audio.wav」に置き換えます。
今必要なのは、必要なファイルを含むテストフォルダーを、テストセットアップの「オーディオ」にコピーし、それをティアダウンで削除することだけです。

これまで考えた中で最もクリーンな方法ではありませんが、それが私のやり方です。

12
Mirko Rossini

オブジェクトを作成する FileFieldとこのフィールドを使用したくないを必要とする場合は、次のような相対パス(既存または非存在)を渡すだけです。

self.example_object = models.ExampleModel({'file': "foo.bar"})
self.example_object.save()

これで使用できるようになります。

1
Ctrl-C