DjangoBrothers BLOG ✍️

2021/02/12

このエントリーをはてなブックマークに追加
Python Django モデル FileField テスト File

Python 指定したサイズのファイルを作成する

Djangoでのテスト用に、指定サイズのファイルを作成したときのメモです。

バージョン

  • Django 3.1.5
  • Python 3.8.4

FileFieldでサイズ制限をかける

DjangoのFileFieldでサイズ制限をかける方法は調べるとたくさん出てきます。

例えば以下のように実装できます。

FileFieldにサイズ制限をかける

from django.core.exceptions import ValidationError
from django.db import models

def validate_file(f):
  limit_mb = 2
  if f.size > limit_mb * 1024 * 1024:
    raise ValidationError(f"アップロード可能なサイズは{limit_mb}MBまでです。")

class MyModel(models.Model):

  file = models.FileField(upload_to=file_upload_path, validators=[validate_file])

指定サイズのファイルを作ってテストする

バリデーションをテストするためのうまい方法が中々見つからなかったのですが、最終的に任意サイズのファイルを作成することで実現できました。(もっと良い方法があるかもしれません。)

os.urandomで任意サイズバイトのランダム文字列を生成して、ContentFileの中身に設定します。

特定サイズのファイルを作成

>>> import os
>>> from django.core.files.base import ContentFile

>>> f = ContentFile(os.urandom(10), "test.txt")
>>> f.size
10
>>> f.read()
b'}\xdbu\xcb\xa9\xf9\xce\xb0\x03\xbd'

DjangoのContenFileを使わない場合は、Pythonのwith openの書き方でファイルを開いて書き込む方法でも作成できます。

DRFとpytestを使っていたのでテストは以下のようになりました。

ファイルサイズを指定してテストする

@pytest.mark.django_db
class TestUploadFileView:

  def test_oversize_file_upload_failure(self, client):
    # 2MBより大きいファイルを作成
    f = ContentFile(os.urandom(2 * 1024 * 1024 + 1), "test.txt")
    res = client.post("/api/file_upload/", {"file": f)})

    expected = {
      "error_code": "E001",
      "messages": ["file:アップロード可能なサイズは2MBまでです。"]
    }
    assert res.json()["status_code"] == 400
    assert res.json()["error"] == expected