如何在 Django 中使用 FileField 测试表单?

How can I test a form with FileField in Django?

我有这个表格:

# forms.py

class BookForm(forms.ModelForm):

    class Meta:
        model = Book
        fields = ['book_title', 'language', 'author', 'release_year', 'genre', 'ages', 'cover']

字段类型: 其中 book_titleauthorCharFieldlanguagegenre 也是 CharField 但对于他们我有选择权 release_yearagesIntegerField,最后的 coverFileField.

选择选项:

# models.py
ENGLISH = 'english'
LANGUAGE_CHOICES = (
    (ENGLISH, 'English'),
)

ADVENTURE = 'adventure'
GENRE_CHOICES = (
    (ADVENTURE, 'Adventure'),
)

现在:我想测试这个表格,但我不知道如何测试cover,这是我的表格测试。

# test_forms.py
from .. import forms
from django.core.files import File


class TestBookForm:
    def test_form(self):
        form = forms.BookForm(data={})
        assert form.is_valid() is False, 'Should be invalid if no data is given'

        img = File(open('background'))

        data = {'book_title': 'Lord Of The Rings',
                'language': 'english',
                'author': 'J. R. R. Tolkien',
                'release_year': 1957,
                'genre': 'adventure',
                'ages': 16,
                'cover': img}

        form = forms.BookForm(data=data)

        assert form.is_valid() is True

我试过了: 从 django.core.files.uploadedfile 导入 SimpleUploadedFile

img = open('background')
uploaded = SimpleUploadedFile(img.name, img.read())
{'cover': uploaded}

这是我的错误:

E       assert False is True
E        +  where False = <bound method BaseForm.is_valid of <BookForm bound=True, valid=False, fields=(book_title;language;author;release_year;genre;ages;cover)>>()
E        +    where <bound method BaseForm.is_valid of <BookForm bound=True, valid=False, fields=(book_title;language;author;release_year;genre;ages;cover)>> = <BookForm bound=True, valid=False, fields=(book_title;language;author;release_year;genre;ages;cover)>
.is_valid

注意: 我使用 Python 3.5Django 1.9.4 并使用 py.test.

开始测试

更新: 如果我尝试 open('background.jpg') 不工作。 错误: FileNotFoundError: [Errno 2] No such file or directory: 'background.jpg' 我修正了这个

更新 2:

我尝试使用mock

from django.core.files import File
import mock

file_mock = mock.MagicMock(spec=File, name='FileMock')
file_mock.name = 'test1.jpg'

{'cover': file_mock}

我尝试使用InMemoryUploadedFile

from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
from PIL import Image

im = Image.new(mode='RGB', size=(200, 200))  # create a new image using PIL
im_io = BytesIO()  # a StringIO object for saving image
im.save(im_io, 'JPEG')  # save the image to im_io
im_io.seek(0)  # seek to the beginning

image = InMemoryUploadedFile(
    im_io, None, 'random-name.jpg', 'image/jpeg', None, None
)

{'cover': image}

我修复了图片的路径。

要么在存储库中创建一个文件,使其物理存在,要么为文件模拟测试。

尝试THIS


编辑

尝试传递完整路径

import os
from django.conf import settings
file_path = os.path.join(settings.BASE_DIR, your_folder, background.jpg)

我找到问题了这是我的代码:

#test_forms.py
from .. import forms
from django.core.files.uploadedfile import SimpleUploadedFile
import os

TEST_DIR = os.path.dirname(os.path.abspath(__file__))
TEST_DATA_DIR = os.path.join(TEST_DIR, 'data')


class TestBookForm:
    def test_form(self):
        form = forms.BookForm(data={})
        assert form.is_valid() is False, 'Should be invalid if no data is given'

        test_image_path = os.path.join(TEST_DATA_DIR, 'background.jpg')

        data = {'book_title': 'Lord Of The Rings',
                'language': 'english',
                'author': 'J. R. R. Tolkien',
                'release_year': 1957,
                'genre': 'adventure',
                'ages': 16}

        with open(test_image_path, 'rb') as f:
            form = forms.BookForm(data=data, files={'cover': SimpleUploadedFile('cover', f.read())})
            assert form.is_valid(), 'Invalid form, errors: {}'.format(form.errors)

更多信息在 docs