質問

FileField を持ついくつかのモデルのテストを構築しようとしています。モデルは次のようになります。

class SolutionFile(models.Model):
    '''
    A file from a solution.
    '''
    solution = models.ForeignKey(Solution)
    file = models.FileField(upload_to=make_solution_file_path)

次の 2 つの問題に遭遇しました。

  1. を使用してフィクスチャにデータを保存する場合 ./manage.py dumpdata, 、ファイルの内容は保存されず、ファイル名のみがフィクスチャに保存されます。ファイルの内容はデータベースに保存されないため、これは予想される動作であると思いますが、テスト用のフィクスチャに何らかの方法でこの情報を含めたいと考えています。

  2. 次のようなファイルをアップロードするためのテストケースがあります。

    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)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top