Djangoでのテスト(パート2)–モデルマミーとDjangoのテストフィクスチャ

Djangoでのテスト(パート2)–モデルマミーとDjangoのテストフィクスチャ

前回のhttps://realpython.com/testing-in-django-part-1-best-practices-and-examples/[post]では、Djangoでのテストを紹介し、ベストプラクティスといくつかの例。 今回はもう少し複雑な例を示し、サンプルデータを作成するためのhttps://github.com/vandersonmota/model_mommy[Model Mommy]を紹介します。

なぜ気にする必要があるのですか?

前回の投稿で、「https://github.com/rbarrois/factory_boy[factory_boy]、https://github.com/vandersonmota/model_mommy[model_mommy]、およびhttps://pypi.python.org/pypi/mock [mock]はすべて、フィクスチャまたはORMの代わりに使用され、テストに必要なデータを取り込みます。 フィクスチャとORMの両方が遅くなる可能性があり、モデルが変更されるたびに更新する必要があります。」

要約すると、Django Testing Fixturesは次の理由で問題があります。

  • モデル/スキーマが変更されるたびに更新する必要があり、

  • 本当に、本当に遅いです。そして

  • ハードコーディングされたデータにより、テストが将来失敗する場合があります。

そのため、Model Mommyを使用することで、ロードが速くなり、時間の経過とともに保守がはるかに容易になるフィクスチャを作成できます。

Djangoテストフィクスチャ

最後の投稿でモデルをテストするための例を見てみましょう:

class WhateverTest(TestCase):

    def create_whatever(self, title="only a test", body="yes, this is only a test"):
        return Whatever.objects.create(
            title=title, body=body, created_at=timezone.now())

    def test_whatever_creation(self):
        w = self.create_whatever()
        self.assertTrue(isinstance(w, Whatever))
        self.assertEqual(w.__unicode__(), w.title)

ここでは、単に `+ Whatever()+`オブジェクトを作成し、作成されたタイトルが期待されるタイトルと一致したことを表明しました。

repoからプロジェクトをダウンロードした場合、サーバーを起動してテストを実行します。

$ coverage run manage.py test whatever -v 2

上記のテストに合格することがわかります。

test_whatever_creation (whatever.tests.WhateverTest) ... ok

これで、毎回(退屈な!)属性ごとに新しいインスタンスを作成する代わりに、Model Mommyを使用してプロセスを合理化できます。

モデルママ

インストール:

$ pip install model_mommy

モデルがどのように見えるか覚えていますか?

class Whatever(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return self.title

これで、上記のテストをはるかに簡単に書き直すことができます。

from model_mommy import mommy

class WhateverTestMommy(TestCase):

    def test_whatever_creation_mommy(self):
        what = mommy.make(Whatever)
        self.assertTrue(isinstance(what, Whatever))
        self.assertEqual(what.__unicode__(), what.title)

それを実行します。 合格しましたか。

簡単だった? 引数を渡す必要はありません。

新しいモデル

もう少し複雑な例を見てみましょう。

セットアップ

新しいアプリを作成します。

$ python manage.py startapp whatevs

_settings.py_ファイルの `+ Installed_Apps +`にアプリを追加します

モデルを作成します。

from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin

class Forum(models.Model):
    title = models.CharField(max_length=100)

    def __unicode__(self):
        return self.title

class Post(models.Model):
    title = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    creator = models.ForeignKey(User, blank=True, null=True)
    forum = models.ForeignKey(Forum)
    body = models.TextField(max_length=10000)

    def __unicode__(self):
        return unicode(self.creator) + " - " + self.title

DBを同期します。

カバレッジレポートはどのようなものですか?

Model Mommy test coverage、width = 535 、height = 489

Test

テストを追加します。

from model_mommy import mommy
from django.test import TestCase
from whatevs.models import Forum, Thread

class WhateverTestMommy(TestCase):

    def test_forum_creation_mommy(self):
        new_forum = mommy.make('whatevs.Forum')
        new_thread = mommy.make('whatevs.Thread')
        self.assertTrue(isinstance(new_forum, Forum))
        self.assertTrue(isinstance(new_thread, Thread))
        self.assertEqual(new_forum.__unicode__(), new_forum.title)
        self.assertEqual(
            new_thread.__unicode__(),
            (str(new_thread.forum) + " - " + str(new_thread.title)))

テストを再実行し(合格するはずです)、カバレッジレポートを作成します。

$ coverage run manage.py test whatevs -v 2
$ coverage html

え?

JSONフィクスチャを使用して上記のテストを実行してみて、Django Testing Fixturesを使用してテストを設定する方法を確認してください。

次のチュートリアルで何が用意されるかわかりませんので、何が見たいか教えてください。 コードhttps://github.com/mjhea0/testing-in-django [こちら]を入手してください。 質問がある場合は、以下にコメントしてください。 乾杯!