Объекты меняются местами при выполнении тестов в django
Сразу хочу извиниться, если я что-то неправильно объяснил. Я пишу это с помощью google translate
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:\Projects\project\news\tests.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:\Users\zepte\.virtualenvs\project-a8cUl3-w\lib\site-packages\django\test\testcases.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:\Projects\project\news\tests.py", line 37, in test_multiple_news
self.assertQuerysetEqual(response.context['last_20_news'], ['<News: News title 2>', '<News: News title 1>'])
File "C:\Users\zepte\.virtualenvs\project-a8cUl3-w\lib\site-packages\django\test\testcases.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'...
Результат, а именно объекты ( ['<News: News title 2>', '<News: News title 1>'] ) в тестах (test_multiple_news и test_multiple_news_from_category) меняются местами каждый раз, когда я запускаю тест, и я хочу знать, почему это происходит.
Используя:
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)
оба предмета будут иметь одинаковый pub_date
. Вы должны использовать:
def create_news(category, title, text='news text', pub_date=None):
if pub_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 import freeze_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')
# …
Вы должны применять ту же логику к элементам, где вы делаете множество вставок близко друг к другу.