10

または、「ユニットテストを簡単にするためにデータベーススキーマを設計する方法は?」

ちなみに、これと非常によく似た質問があります: 外部キーを使用してDjangoでモデルをテストする方法

フレームワークDjangoを使用するプロジェクトのTDD方法論に従おうとしています。モデルとその機能(メソッド、シグナルなどを保存する)、およびモデルに依存するその他の高レベルの関数を作成してテストしています。

単体テストは可能な限り分離する必要があることは理解していますが、テストごとにFactoryBoyを使用して多くのテーブルとリレーションを作成していることに気付きます。そのため、モデルで何かが変更されると多くのテストが失敗する可能性があるため、テストは十分に強力ではありません。

これらすべての依存関係を回避し、テストをよりクリーンにする方法は?

実際のテストの前に、その定型文をすべて避けるために、皆さんは何をお勧めしますか?

ベストプラクティスは何ですか?

4

3 に答える 3

13

テストのベストプラクティスのリストはありません。それはあなたとあなたが取り組んでいる特定のプロジェクトのために働く多くのものです。彼が言うとき、私はピリクに同意します:

テスト方法に基づいてソフトウェアを設計するべきではありません

ただし、優れたモジュール式のソフトウェア設計があれ、適切にテストするのは簡単です。

私は最近、自分の仕事で単体テストに少し興味があり、Pythonでいくつかの面白くて便利なツールを見つけました。テストのsetUp()メソッドで多くのオブジェクトを準備する代わりに、 FactoryBoyはそれらのツールの1つです。クラスでは、モデルごとにファクトリを定義し、必要に応じてそれらを一括で生成できます。

Mockerを試すこともできます。これは、オブジェクトをモックするライブラリです。Pythonではすべてがオブジェクトであるため、関数もモックできます。特定の時刻にXイベントを生成する関数をテストする必要がある場合に便利です。たとえば、午前10時にメッセージを送信し、常に「10:00 am」を返すdatetime.datetime.now()のモックを作成し、そのモックでその関数呼び出します。

フロントエンドもテストする必要がある場合、またはテストに人間との対話が必要な場合(OAuthを実行する場合など)、Seleniumを使用してこれらのフォームに入力して送信します。

あなたの場合、FactoryBoyとの関係を持つオブジェクトを準備するために、Factory._prepare()メソッドを上書きしてみることができます。この単純なdjangoモデルでそれを実行しましょう。

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(User, blank=True, null=True)

    # ...

それでは、簡単なUserFactoryを定義しましょう。

class UserFactory(factory.Factory):
    FACTORY_FOR = User

    first_name = 'Foo'
    last_name = factory.Sequence(lambda n: 'Bar%s' % n)
    username = factory.LazzyAttribute(lambda obj: '%s.%s' % (obj.first_name, obj.last_name))

ここで、ファクトリが5つのメンバーを持つグループを生成する必要がある、または必要だとしましょう。GroupFactoryは次のようになります。

class GroupFactory(factory.Factory):
    FACTORY_FOR = Group

    name = factory.Sequence(lambda n: 'Test Group %s' % n)

    @classmethod
    def _prepare(cls, create, **kwargs):
        group = super(GroupFactory, cls)._prepare(create, **kwargs)
        for _ in range(5):
            group.members.add(UserFactory())
        return group

これがお役に立てば幸いです、または少なくともあなたに光を与えました。ここでは、私が言及したツールに関連するリソースへのリンクをいくつか残しておきます。

ファクトリーボーイ:https ://github.com/rbarrois/factory_boy

モッカー: http: //niemeyer.net/mocker

Selenium:http ://selenium-python.readthedocs.org/en/latest/index.html

そして、テストに関するもう1つの便利なスレッド:

Djangoで「異なるレイヤー」をテストするためのベストプラクティスは何ですか?

于 2012-08-14T20:36:35.050 に答える
2

Mixerを使用してみてください。'factory_boy'よりもはるかに簡単で、はるかに強力です。工場をセットアップする必要はなく、必要なときにデータを取得できます。

from mixer.backend.django import mixer

mixer.blend(MyModel)
于 2014-01-07T19:27:39.143 に答える
0

あなたがそんなに深く行く必要があるかどうかは本当にわかりません。テスト方法に基づいてソフトウェアを設計するのではなく、使用しているツールにテスト方法を適合させる必要があります。

あるモデルをテストするときにFKモデルとM2Mモデルをモックするように、そのレベルの粒度を取得したいとしますか?何かのようなもの

class Invoice(models.Model):
    client = models.ForeignKey(Client)

Invoiceテストでは、モデルを扱わずに、モデルのみをテストする必要がありますClient。そうですか?では、データベースのバックエンドもモックして、モデルが何をすべきかだけをテストしてみませんか?

私のポイントは、あなたがそのレベルに到達する必要はないということです。シグナルやメソッドなどの重要なものについてモデルにいくつかのテストを追加し、モデルの作成が機能していることを確認し(データベースを信頼している場合はこれを回避することもできます)、外部モデルを操作する必要がある場合は、必要なものを作成するだけですテストのsetUp()方法。

また、必要に応じて、Pythonのモックライブラリ( http://www.voidspace.org.uk/python/mock/)を使用して好きなものをモックできます。本当にTDDを実行したい場合は、各テストでFKをモックするために使用できますが、そのモデルを変更する場合は、すべてのモッカーも変更する必要があります。

于 2012-08-09T16:06:40.030 に答える