在django中运行测试时会交换对象



如果我解释不正确,我想立即道歉。我通过谷歌翻译写这篇文章

Django在一次测试后显示了测试中的错误。测试成功一次,然后失败。如果我什么都不改变,那么一个仍然通过,另一个没有。

测试

def create_category():
return Category.objects.create(category_title='Category title', slug='category-title')

def create_news(category, title, text='news text', pub_date=timezone.now()):
return News.objects.create(category=category, image=None, title=title,
text=text, pub_date=pub_date)

class HomePageTestCase(TestCase):
def test_no_news(self):
response = self.client.get(reverse('news:home'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'News not found')
self.assertQuerysetEqual(response.context['last_20_news'], [])
def test_one_news(self):
category = create_category()
news = create_news(category, 'News title')
response = self.client.get(reverse('news:home'))
self.assertQuerysetEqual(response.context['last_20_news'], ['<News: News title>'])
def test_multiple_news(self):
category = create_category()
news_1 = create_news(category, 'News title 1')
news_2 = create_news(category, 'News title 2')
response = self.client.get(reverse('news:home'))
self.assertQuerysetEqual(response.context['last_20_news'], ['<News: News title 2>', '<News: News title 1>'])

class CategoryPageTestCase(TestCase):
def test_no_news_from_category(self):
category = create_category()
response = self.client.get(category.get_absolute_url())
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'News not found')
self.assertQuerysetEqual(response.context['news_from_category'], [])
def test_one_news_from_category(self):
category = create_category()
news = create_news(category, 'News title')
response = self.client.get(category.get_absolute_url())
self.assertQuerysetEqual(response.context['news_from_category'], ['<News: News title>'])
def test_multiple_news_from_category(self):
category = create_category()
news_1 = create_news(category, 'News title 1')
news_2 = create_news(category, 'News title 2')
response = self.client.get(category.get_absolute_url())
self.assertQuerysetEqual(response.context['news_from_category'], ['<News: News title 2>', '<News: News title 1>'])

为其创建测试的视图

class HomePageView(ListView):
template_name = 'index.html'
context_object_name = 'last_20_news'
def get_queryset(self):
return News.objects.order_by('-pub_date')[:20].select_related('category')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(HomePageView, self).get_context_data()
context['categories'] = Category.objects.all()
return context

class NewsFromCategoryView(ListView):
template_name = 'news/category_page.html'
slug_url_kwarg = 'category_slug'
paginate_by = 20
context_object_name = 'news_from_category'
def get_queryset(self):
return News.objects.filter(category__slug=self.kwargs['category_slug']).select_related('category')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(NewsFromCategoryView, self).get_context_data()
context['category'] = Category.objects.get(slug=self.kwargs['category_slug'])
return context

控制台结果

λ python manage.py test news
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F..F..
======================================================================
FAIL: test_multiple_news_from_category (news.tests.CategoryPageTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:Projectsprojectnewstests.py", line 59, in test_multiple_news_from_category
self.assertQuerysetEqual(response.context['news_from_category'], ['<News: News title 2>', '<News: News title 1>'])
File "C:Userszepte.virtualenvsproject-a8cUl3-wlibsite-packagesdjangotesttestcases.py", line 1072, in assertQuerysetEqual
return self.assertEqual(list(items), values, msg=msg)
AssertionError: Lists differ: ['<News: News title 1>', '<News: News title 2>'] != ['<News: News title 2>', '<News: News title 1>']
First differing element 0:
'<News: News title 1>'
'<News: News title 2>'
- ['<News: News title 1>', '<News: News title 2>']
?                     ^                       ^
+ ['<News: News title 2>', '<News: News title 1>']
?                     ^                       ^

======================================================================
FAIL: test_multiple_news (news.tests.HomePageTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:Projectsprojectnewstests.py", line 37, in test_multiple_news
self.assertQuerysetEqual(response.context['last_20_news'], ['<News: News title 2>', '<News: News title 1>'])
File "C:Userszepte.virtualenvsproject-a8cUl3-wlibsite-packagesdjangotesttestcases.py", line 1072, in assertQuerysetEqual
return self.assertEqual(list(items), values, msg=msg)
AssertionError: Lists differ: ['<News: News title 1>', '<News: News title 2>'] != ['<News: News title 2>', '<News: News title 1>']
First differing element 0:
'<News: News title 1>'
'<News: News title 2>'
- ['<News: News title 1>', '<News: News title 2>']
?                     ^                       ^
+ ['<News: News title 2>', '<News: News title 1>']
?                     ^                       ^

----------------------------------------------------------------------
Ran 6 tests in 0.272s
FAILED (failures=2)
Destroying test database for alias 'default'...

再次运行测试

λ python manage.py test news
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
......
----------------------------------------------------------------------
Ran 6 tests in 0.354s
OK
Destroying test database for alias 'default'...

每次运行测试时,都会交换测试(test_multiple_News和test_multipple_News_from_category(中的对象(['<News:News title 2>','<News:News title 1>'](,我想知道为什么会发生这种情况。

使用:

def create_news(category, title, text='news text', pub_date=timezone.now()):
return News.objects.create(category=category, image=None, title=title, text=text, pub_date=pub_date)

两个项目将具有相同的CCD_ 1。您应该使用:

def create_news(category, title, text='news text', pub_date=None):
ifpub_date is not None:
pub_date = timezone.now()
return News.objects.create(category=category, image=None, title=title, text=text, pub_date=pub_date)

但仍然有可能这两个项目插入的速度如此之快,以至于它们具有相同的时间戳。因此,最好使用freezegun[GitHub]这样的工具来确保两者之间至少有几毫秒的时间:

from freezegun importfreeze_time
class HomePageTestCase(TestCase):
# …
@freeze_time('2021-12-26', auto_tick_seconds=15)
def test_multiple_news(self):
category = create_category()
news_1 = create_news(category, 'News title 1')
news_2 = create_news(category, 'News title 2')
# …

您应该将相同的逻辑应用于使多个插入彼此靠近的项。

最新更新