Django テストフィクスチャを使用して FileField をテストする
-
20-09-2019 - |
質問
FileField を持ついくつかのモデルのテストを構築しようとしています。モデルは次のようになります。
class SolutionFile(models.Model):
'''
A file from a solution.
'''
solution = models.ForeignKey(Solution)
file = models.FileField(upload_to=make_solution_file_path)
次の 2 つの問題に遭遇しました。
を使用してフィクスチャにデータを保存する場合
./manage.py dumpdata
, 、ファイルの内容は保存されず、ファイル名のみがフィクスチャに保存されます。ファイルの内容はデータベースに保存されないため、これは予想される動作であると思いますが、テスト用のフィクスチャに何らかの方法でこの情報を含めたいと考えています。次のようなファイルをアップロードするためのテストケースがあります。
def test_post_solution_file(self): import tempfile import os filename = tempfile.mkstemp()[1] f = open(filename, 'w') f.write('These are the file contents') f.close() f = open(filename, 'r') post_data = {'file': f} response = self.client.post(self.solution.get_absolute_url()+'add_solution_file/', post_data, follow=True) f.close() os.remove(filename) self.assertTemplateUsed(response, 'tests/solution_detail.html') self.assertContains(response, os.path.basename(filename))
このテストは問題なく機能しますが、終了後、アップロードされたファイルがメディア ディレクトリに残ります。もちろん、削除は次の方法で処理できます。 tearDown()
, 、しかし、Django にはこれに対処する別の方法があるかどうか疑問に思いました。
私が考えていた解決策の 1 つは、テスト用に別のメディア フォルダーを使用し、テスト フィクスチャとの同期を維持することでした。別のメディアディレクトリを指定する方法はありますか? settings.py
テストはいつ実行されますか?また、メディア フォルダー内のファイルを同期できるように、dumpdata に何らかのフックを含めることはできますか?
では、ファイルに関係する単体テストを処理する、より Python または Django に特化した方法はあるのでしょうか?
解決
Djangoは、実際のファイルシステムで約いじくることなく、FileFieldsのテストを記述するのに最適な方法を提供 - 。SimpleUploadedFileを使用する
from django.core.files.uploadedfile import SimpleUploadedFile
my_model.file_field = SimpleUploadedFile('best_file_eva.txt', 'these are the file contents!')
これは、Djangoの魔法の機能、つまり、ドント・ショーアップ・イン・ザ・ドキュメント:)の一つです。しかし、ここでのhref="https://docs.djangoproject.com/en/dev/ref/forms/api/#binding-uploaded-files-to-a-form">を
他のヒント
あなたはMEDIA_ROOT
デコレータ<のhref =「https://docs.djangoproject.com/en/1.10/topics/testing/tools/#django.test.override_settings」のrel =を使用して、テストの設定@override_settings()
を上書きすることができます"nofollowをnoreferrer">文書のよう:
from django.test import override_settings
@override_settings(MEDIA_ROOT='/tmp/django_test')
def test_post_solution_file(self):
# your code here
私は前に全体のギャラリーアプリのためのユニットテストを書いた、そしてどのような私のためによく働いたことは、一時的なディレクトリにテストファイルのコピーを作成し、その後それらをすべて削除するには、Pythonの一時ファイルとshutilモジュールを使用していた。
次の例では/完全に動作していないが、正しい道にあなたを取得する必要があります:
import os, shutil, tempfile
PATH_TEMP = tempfile.mkdtemp(dir=os.path.join(MY_PATH, 'temp'))
def make_objects():
filenames = os.listdir(TEST_FILES_DIR)
if not os.access(PATH_TEMP, os.F_OK):
os.makedirs(PATH_TEMP)
for filename in filenames:
name, extension = os.path.splitext(filename)
new = os.path.join(PATH_TEMP, filename)
shutil.copyfile(os.path.join(TEST_FILES_DIR, filename), new)
#Do something with the files/FileField here
def remove_objects():
shutil.rmtree(PATH_TEMP)
私はユニットテストのそれらのsetUp()メソッドとtearDown内のメソッド()メソッドを実行し、それは素晴らしい作品!あなたは、再利用可能で予測されているあなたのFileFieldにをテストするために、ファイルのクリーンコピーを持っています。
これは私が私のテストのために何をしたかです。ファイルをアップロードした後、それは私の組織モデルのオブジェクトの写真プロパティで終わる必要があります:
import tempfile
filename = tempfile.mkstemp()[1]
f = open(filename, 'w')
f.write('These are the file contents')
f.close()
f = open(filename, 'r')
post_data = {'file': f}
response = self.client.post("/org/%d/photo" % new_org_data["id"], post_data)
f.close()
self.assertEqual(response.status_code, 200)
## Check the file
## org is where the file should end up
org = models.Organization.objects.get(pk=new_org_data["id"])
self.assertEqual("These are the file contents", org.photo.file.read())
## Remove the file
import os
os.remove(org.photo.path)