理解不稳定的Django测试:实例创建顺序影响序列化返回数组顺序
顺序异常的原因
- Django 多对多关联关系默认不保证返回数据的顺序:你在创建
Client时传入agents=[agent1, agent2],仅代表插入关联记录的顺序,但是默认查询多对多关联数据时,数据库没有固定的排序规则,返回顺序会受数据库查询执行计划、数据存储分布、环境负载等因素影响。本地环境刚好返回顺序符合预期,CI 环境出现差异是正常现象,和--parallel并行参数没有直接关系。 - 如果你的序列化器没有显式指定
agents的排序逻辑,序列化输出的数组顺序完全依赖数据库返回的 QuerySet 顺序,自然会出现偶发乱序的问题。
更健壮的实现方案
方案1:序列化层固定排序(适合业务要求返回顺序固定的场景)
直接在序列化器中给关联的agents字段指定排序规则,保证无论数据库返回顺序如何,序列化输出的顺序都是固定的,示例如下:
# 在WebhookClientSerializer中定义agents字段时指定排序 agents = AgentSerializer( many=True, # 可根据业务需求选择排序字段,比如id、创建时间、邮箱等 queryset=AgentUser.objects.order_by("email") )
方案2:测试层调整断言逻辑(适合业务不要求返回顺序的场景)
测试时不要依赖数组的索引顺序,改用集合校验元素完整性,或者先排序再断言,修改后的测试代码示例:
class WebhookClientSerializerTestCase(TestCase): def test_serializes_agent_from_client(self): agent1 = factories.AgentUserFactory(email='dave@agently.com') agent2 = factories.AgentUserFactory(email='jim@agently.com') client = factories.ClientFactory(agents=[agent1, agent2]) schema = serializers.WebhookClientSerializer() data = schema.dump(client).data # 方式1:用集合校验返回的邮箱完整,不关心顺序 returned_emails = {item['email'] for item in data['agents']} self.assertEqual(returned_emails, {'dave@agently.com', 'jim@agently.com'}) # 方式2:先排序再断言,避免依赖原始返回顺序 sorted_emails = sorted(item['email'] for item in data['agents']) self.assertEqual(sorted_emails, ['dave@agently.com', 'jim@agently.com'])
内容的提问来源于stack exchange,提问作者John Kealy
相关产品推荐
相关产品推荐

