web-dev-qa-db-ja.com

Djangoクエリセットが等しいことをテストするにはどうすればよいですか?

私は私のDjangoビューをテストしようとしています。このビューはクエリセットをテンプレートに渡します:

def merchant_home(request, slug):
  merchant = Merchant.objects.get(slug=slug)
  product_list = merchant.products.all()
  return render_to_response('merchant_home.html',
                            {'merchant': merchant,
                            'product_list': product_list},
                            context_instance=RequestContext(request))

そしてテスト:

  def test(self):
    "Merchant home view should send merchant and merchant products to the template"
    merchant = Merchant.objects.create(name='test merchant')
    product = Product.objects.create(name='test product', price=100.00)
    merchant.products.add(product)

    test_client = Client()
    response = test_client.get('/' + merchant.slug)
    # self.assertListEqual(response.context['product_list'], merchant.products.all())
    self.assertQuerysetEqual(response.context['product_list'], merchant.products.all())

[〜#〜] edit [〜#〜]self.assertQuerysetEquaではなくself.assertListEquallを使用しています。残念ながらこれはまだ機能せず、ターミナルには次のように表示されます:['<Product: Product object>'] != [<Product: Product object>]


assertListEqualレイズ:'QuerySet' object has no attribute 'difference'およびassertEqualも機能しませんが、self.assertSetEqual(response.context['product_list'][0], merchant.products.all()[0])はパスします。

これは、同じモデルインスタンスが含まれていても、QuerySetは異なるオブジェクトであるためと考えられます。

2つのクエリセットに同じデータが含まれていることをテストするにはどうすればよいですか?私はこれを正しくテストしていますか?これは私の4日目の学習ですDjangoですから、できればベストプラクティスを知りたいと思います。ありがとうございます。

30
jz999

2つのクエリセットを比較するために作成された assertQuerysetEqual を使用します。テストで使用できるようにするには、DjangoのDjango.test.TestCaseをサブクラス化する必要があります。

24
girasquid

デフォルトでは、assertQuerysetEqualは最初の引数にrepr()を使用します。これが、クエリセットの比較で文字列に問題があった理由です。

これを回避するには、 transform引数を上書きするrepr()を使用しないlambda関数で上書きします。

self.assertQuerysetEqual(queryset_1, queryset_2, transform=lambda x: x)
21
dspacejs

私は同じ問題を抱えていました。 assertQuerysetEqualの2番目の引数は、文字列として予期されるrepr()のリストである必要があります。 Djangoテストスイートの例です:

self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"], ordered=False)
8
sk1p

_self.assertQuerysetEqual_呼び出し内のクエリセットの各エントリをmapからrepr()を使用してこの問題を解決しました。

_self.assertQuerysetEqual(queryset_1, map(repr, queryset_2))
_
4
DrBuck

Pytestを使用する場合、別の(ただし、必ずしも優れているとは限りません)メソッドは次のようになります(たとえば、ビューのコンテキストをテストします)。

all_the_things = Things.objects.all()
assert set(list(response.context_data['all_the_things'])) == set(list(all_the_things))

これにより、リスト、次にセットに変換され、別のセットと直接比較できます。ただし、setの動作には注意してください。重複が削除されるため、意図したとおりにならない場合があります。

2
Chris

self.assertCountEqual(queryset1, queryset2)を使用しても問題が解決することがわかりました。

0