You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Django autocomplete light的Select2QuerySetView单元测试覆盖查询分支

如何测试Django AutoComplete Light的查询分支以实现全代码覆盖

你当前的测试仅覆盖了不带查询参数的请求场景,所以if self.q:内部的过滤逻辑完全没被执行到。要实现完整的代码覆盖,你需要在测试中模拟用户输入搜索关键词的行为——也就是发送带q查询参数的GET请求。

下面是完善后的测试类,能覆盖所有代码分支:

from django.test import TestCase
from django.urls import reverse
from django.db.models import Q
from .models import Item

class TestItemAutoComplete(TestCase):
    def setUp(self):
        # 预先创建测试数据,保证每次测试都有稳定的数据源
        self.item1 = Item.objects.create(id=101, name="办公笔记本")
        self.item2 = Item.objects.create(id=202, name="无线静音鼠标")
        self.item3 = Item.objects.create(id=303, name="机械游戏键盘")

    def test_visit_without_query(self):
        # 保留原测试:覆盖无查询参数的分支
        response = self.client.get(reverse('buy_invoice_items_autocomplete'))
        self.assertEqual(response.status_code, 200)
        # 额外验证返回全部数据
        self.assertEqual(len(response.json()['results']), 3)

    def test_visit_with_exact_id_query(self):
        # 测试按ID精确匹配的分支(对应Q(id__iexact=self.q))
        response = self.client.get(
            reverse('buy_invoice_items_autocomplete'),
            {'q': '202'}
        )
        self.assertEqual(response.status_code, 200)
        results = response.json()['results']
        # 验证仅返回匹配ID的条目
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]['id'], str(self.item2.id))
        self.assertEqual(results[0]['text'], self.item2.name)

    def test_visit_with_name_contain_query(self):
        # 测试按名称模糊匹配的分支(对应Q(name__icontains=self.q))
        response = self.client.get(
            reverse('buy_invoice_items_autocomplete'),
            {'q': '鼠标'}
        )
        self.assertEqual(response.status_code, 200)
        results = response.json()['results']
        # 验证返回包含关键词的条目
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]['id'], str(self.item2.id))

    def test_visit_with_no_match_query(self):
        # 测试无匹配结果的场景,覆盖过滤后空QuerySet的情况
        response = self.client.get(
            reverse('buy_invoice_items_autocomplete'),
            {'q': '不存在的关键词'}
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.json()['results']), 0)

关键优化点:

  • 用reverse('buy_invoice_items_autocomplete')替代硬编码URL,符合Django最佳实践,避免URL变更导致测试失效。
  • 通过setUp预先初始化测试数据,确保测试环境的一致性。
  • 拆分多个测试用例,分别覆盖无查询、ID精确匹配、名称模糊匹配、无匹配结果这四类场景,确保每一行代码都被执行到。
  • 验证返回的JSON结构(Select2的响应格式固定为包含results的字典),不仅保证代码覆盖,还能验证业务逻辑的正确性。

这样修改后,Coverage工具就会检测到if self.q:及后续的过滤代码都被执行过,实现完整的代码覆盖了。

内容的提问来源于stack exchange,提问作者Ahmed Wagdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:51:17