我在Django单元测试(Python 3.4)中遇到了AssertEquals()的一些奇怪行为。以下测试会导致断言错误,如:
第113行,在test_index_view_with_questions_without_choices中 self.assertEqual(response.context [' lastest_question_list'],[]) 断言错误:[]!= []
以下是测试本身:
def test_index_view_with_questions_without_choices(self):
'''
If a question has no choices it should not be
displayed on the questions index page no matter if it's
a past or a future question.
'''
create_question_with_no_choices(question_text='no choices q1', days=-5)
create_question_with_no_choices(question_text='no choices q2', days=5)
response = self.client.get(reverse('polls:index'))
self.assertContains(response, 'No polls are available.', status_code=200)
self.assertEqual(response.context['lastest_question_list'], [])
改变最后一行如下:
self.assertEqual(len(response.context['lastest_question_list']), 0)
让测试正常运行,但我无法理解它拒绝使用列表本身。
我在同一个应用和项目中也有一个非常相似的测试,工作得很好:
def test_index_view_with_no_questions(self):
'''
If no questions exist, an appropriate message
should be displayed.
'''
response = self.client.get(reverse('polls:index'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'No polls are available.')
self.assertQuerysetEqual(response.context['lastest_question_list'], [])
这里有视图本身来显示Queryset的定义方式:
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'lastest_question_list'
def get_queryset(self):
'''
Returns last five published questions
(not including those set to be published in the future)
Also excludes the questions with an empty choice_set.
'''
qset = Question.objects.annotate(choices_count=Count('choice'))
qset = qset.filter(choices_count__gte=1, pub_date__lte=timezone.now())
qset = qset.order_by('-pub_date')[:5]
return qset
P.S。:我发现了HERE描述的类似问题,但我仍然对实际导致此类行为的原因感到困惑。即使我知道如何使测试在这个特定的例子中工作,但我仍然很重要的是要了解正在发生的事情。 :)
答案 0 :(得分:1)
首先,我怀疑并且您检查过,response.context['latest_question_list']
是一个查询集,因此您无法直接将查询集对象与列表对象进行比较。
此外,django doc中记录了assertQuerysetEqual
,引用此处:
TransactionTestCase.assertQuerysetEqual(qs,values,transform = repr,ordered = True,msg = None)
qs和值的内容的比较使用 功能转换;默认情况下,这意味着每个的repr() 比较价值。如果repr()没有,则可以使用任何其他可调用的 提供独特或有用的比较。
您可以看到assertQuerysetEqual
正在将查询集中的每个值与您提供的列表进行比较,因此它将遍历整个事物并比较每个值。这就是为什么它会通过测试而失败assertEqual
。