Django分页测试移类后异常:分页数量不符问题排查
问题:Django分页测试用例迁移后数量异常
将Django分页测试用例从独立的PaginatorViewsTest类移至PostPagesTests类后,出现分页数量异常:
- 创建13篇测试Post时,第二页显示4篇(预期3篇)
- 创建12篇测试Post时,第二页显示2篇
- 测试用例保留在独立类中则一切正常
相关代码如下:
测试代码
def test_correct_page_context_guest_client(self): posts = [Post(text=f'Тестовый текст {i}', group=self.group0, author=self.user0) for i in range(13)] Post.objects.bulk_create(posts) pages = (reverse('posts:posts_list'), reverse('posts:group_list', kwargs={'slug': f'{self.group0.slug}'}), reverse('posts:profile', kwargs={'username': f'{self.user0.username}'})) for page in pages: for page_number in range(2): with self.subTest(page=page): response = self.guest_client0.get( page, {'page': page_number+1}) self.assertEqual(len(response.context['page_obj']), POSTS_COUNT[page_number])
PostPagesTests类及SetUpClass代码
class PostPagesTests(TestCase): @classmethod def setUpClass(cls): super().setUpClass() cls.user = User.objects.create_user(username='test') cls.user2 = User.objects.create_user(username='test2') cls.user_unfollow = User.objects.create_user(username='test3') cls.guest_client = Client() cls.authorized_client = Client() cls.authorized_client.force_login(cls.user) cls.authorized_client_no_follow = Client() cls.authorized_client_no_follow.force_login(cls.user_unfollow) cls.guest_client0 = Client() cls.user0 = User.objects.create_user(username='auth') cls.group0 = Group.objects.create(title='Тестовая группа', slug='test_group') cls.group = Group.objects.create( title='test', slug='test', description='test' ) cls.group2 = Group.objects.create( title='test2', slug='test2', description='test2' ) cls.post = Post.objects.create( author=cls.user, group=cls.group, text='test' )
原因排查与解决方案
核心问题:SetUpClass中存在额外Post
PostPagesTests.setUpClass最后一行创建了一个额外的cls.post,这个Post会被计入全局的posts_list页面总数中,导致分页计算出错:
- 测试用例创建13篇Post时,全局Post总数为
13+1=14,若每页显示10篇,第二页自然会显示4篇 - 测试用例创建12篇Post时,全局总数为
12+1=13,第二页显示3篇,但你的测试用例统一用POSTS_COUNT断言,导致结果不符合预期 - 而独立测试类中没有这个额外Post,所以分页逻辑正常
解决方案
方案1:清理测试前置数据
在测试用例开始前删除所有Post,避免前置数据干扰:
def test_correct_page_context_guest_client(self): # 清空所有Post,保证测试环境纯净 Post.objects.all().delete() posts = [Post(text=f'Тестовый текст {i}', group=self.group0, author=self.user0) for i in range(13)] Post.objects.bulk_create(posts) # 后续测试代码不变
方案2:移除SetUpClass中的非必要Post
如果cls.post不是该类其他测试用例的必需数据,直接删除setUpClass中创建cls.post的代码即可。
方案3:改用setUp方法初始化数据
若cls.post是其他测试用例需要的,将setUpClass改为setUp方法,让每个测试用例执行前都重新初始化数据,避免测试间的污染:
class PostPagesTests(TestCase): def setUp(self): super().setUp() # 原setUpClass中的初始化代码移到这里 self.user = User.objects.create_user(username='test') # ... 其余初始化代码 ... self.post = Post.objects.create( author=self.user, group=self.group, text='test' )
内容的提问来源于stack exchange,提问作者Fabler
相关产品推荐
相关产品推荐

