DjangoでImageFieldを持つフォームのテスト

DjangoでImageFieldを持ったFormがあるとします。こんな感じ。ModelFormでもいい(というか実際のコードはそっちで書いてる)。

class UploadForm(forms.Form):
    title = forms.CharField()
    photo = forms.ImageField()

これをテストする際にStringIOで適当に作ったダミーを食わせたら「画像じゃないよ!」って怒られた。ダミー画像をテスト用に置いておくのもなんだかなぁ…と思ってたら、そうだ、PIL使ってるんだからPILで生成すればいいじゃないか。

#-*- coding:utf-8 -*-
import io

from PIL import Image
from django.test import TestCase
from django.core.files.uploadedfile import SimpleUploadedFile


class UploadFormTest(TestCase):
    def _get_form_class(self):
        from .forms import UploadForm
        return UploadForm

    def _make_dummy_image(self):
        file_obj = io.BytesIO()
        im = Image.new('RGBA', size=(10, 10), color=(256, 0, 0))
        im.save(file_obj, 'png')
        file_obj.name = 'test.png'
        file_obj.seek(0)
        return file_obj

    def test_it(self):
        img = self._make_dummy_image()
        Form = self._get_form_class()
        form = Form(
            data={'title': 'test title'},
            files={'photo': SimpleUploadedFile(
                img.name,
                img.read(),
                content_type='image/png',
            )},
        )
        self.assertTrue(form.is_valid())

ちなみに環境は Python 3.3 + Django 1.7.0.a です。ソースを追ってみると、form.is_valid() を呼ぶと内部で self.ImageField.to_python() が呼ばれ、さらにそのメソッド内で from django.utils.image import Image; Image.open() しているんですね。

というわけで一年以上ぶりの記事でした。