【Django】テストツールのClientを使ってアップロードファイルのテストをする


投稿日 2023年7月16日 >> 更新日 2023年7月17日

概要

この記事では、フォームから画像ファイルがアップロードされその画像ファイルをDjango側で保存をせずに処理して、その結果を返す工程をテストする例です。
画像ファイルの保存は行わないのでシンプルな使用となります。

実行環境&使用ライブラリ

実行環境
Windows Subsystem for Linux 2
Python 3.7.0
使用ライブラリ ライセンス
Django==2.2.5 BSD
Pillow==9.5.0 HPND

テストを行いたいコード

テストを行いたいコードの範囲は以下のform_validメソッドです。

# views.py

class PostView(generic.FormView):

    template_name = "file_upload/post.html"
    form_class = UploadForm

    def form_valid(self, form):
        upload_file = form.cleaned_data["upload_file"]

        # result = predict(upload_file)
        result = "猫"
        context = {"result": result}

        return render(self.request, "file_upload/post.html", context)

上記の処理内容は、ユーザーがアップロードしたファイルを機械学習モデルのpredict関数に渡して、動物を判定するといった処理です。

結果は「猫」としています。

フォームクラスの内容は以下となります。

# forms.py

from django import forms


class UploadForm(forms.Form):

    upload_file = forms.ImageField(label="アップロード")

テンプレートファイルの内容は以下です。

<!-- post.html -->

<html>
  <body>
{% if not result %}
<form method="POST" enctype='multipart/form-data'>
  {% csrf_token %}
  {{ form.upload_file }}
  <br>
  <input type="submit" value="結果">
</form>
{% else %}
{{ result }}
{% endif %}
  </body>
</html>

フォームに画像ファイルがインプットされ、アップロードされる際の結果は以下のような流れです。

アップロードファイルのテスト

アップロードファイルをテストする場合は、DjangoのClientクラスを使用します。

Clientクラスにはgetやpostといったメソッドがあり、それぞれ疑似的に行われたユーザーからのアクションをテストすることができます。

以下はClientクラスを使用したアップロードファイルに対してのテストケースです。

# tests.py

from django.test import TestCase
from django.urls import reverse


class PostViewTests(TestCase):
    def setUp(self):
        self.url = reverse("file_upload:post")

    def tearDown(self):
        del self.url

    def test_post_pageview(self):
        """
        /ページの表示テスト
        """
        response = self.client.get(self.url)
        self.assertEqual(response.status_code, 200)

    def test_post_result(self):
        """
        /ページでアップロードの結果表示
        """
        # テスト用の画像ファイルを使用して結果表示のテストをする
        with open("file_upload/cat_1.jpg", "rb") as f:
            response = self.client.post(path=self.url, data={"upload_file": f})
        self.assertEqual(response.status_code, 200)
        # response変数に第二引数のテキストが含まれていれば成功
        self.assertContains(response, "猫")

アップロードする画像ファイルが必要なので、テスト用の画像ファイルを準備します。

「with open」としているのは、with節が終了するとファイルを自動的に閉じるとの事で公式では推奨されています。

client.postメソッドの引数である「data」にはフォームクラスで定義している変数名と画像ファイルが辞書型で渡されています({フォームクラスの変数名:画像ファイル})。

assert.Containsでは、response変数の中に第二引数に定義されたテキストが含まれているかをアサートしています。

それでは以上となります。

最後までご覧いただきありがとうございました。