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

Django测试发现异常:admin/models模块被误识别为测试用例

问题

执行./manage.py test时触发如下错误:

...
test_create_default_action_with_deadline (masoon.anomalies.tests.anomaly.AnomalyCreateDefaultAction) ... ok
masoon.actions.admin (unittest.loader._FailedTest) ... ERROR
masoon.actions.models (unittest.loader._FailedTest) ... ERROR
masoon.anomalies.models (unittest.loader._FailedTest) ... ERROR
...
======================================================================
ERROR: masoon.actions.admin (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: masoon.actions.admin
Traceback (most recent call last):
  File "/usr/lib/python3.10/unittest/loader.py", line 470, in _find_test_path
    package = self._get_module_from_name(name)
  File "/usr/lib/python3.10/unittest/loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "/home/vahid/project/py/django/masoon/actions/admin/__init__.py", line 1, in <module>
    from .actions import ActionsAdmin
  File "/home/vahid/project/py/django/masoon/actions/admin/actions.py", line 8, in <module>
    class ActionsAdmin(AbstractBaseAdmin):
  File "/home/vahid/project/py/django/masoon/.venv/lib/python3.10/site-packages/django/contrib/admin/decorators.py", line 100, in _model_admin_wrapper
    admin_site.register(models, admin_class=admin_class)
  File "/home/vahid/project/py/django/masoon/.venv/lib/python3.10/site-packages/django/contrib/admin/sites.py", line 126, in register
    raise AlreadyRegistered(msg)
django.contrib.admin.sites.AlreadyRegistered: The model Action is already registered with 'actions.ActionsAdmin'.

实际问题并非Admin重复注册,而是unittest错误地将admin、models模块识别为测试用例并尝试加载执行。

项目目录结构:

...
├── actions
│   ├── admin
│   │   ├── action_report.py
│   │   ├── actions.py
│   │   ├── answer.py
│   │   ├── __init__.py
│   ├── api
│   |   ├── ...
│   ├── tests
│   |   ├── actions.py
│   |   ├── answers.py
...
│   ├── apps.py
│   ├── __init__.py
│   ├── models
│   │   ├── action.py
│   │   ├── action_report.py
│   │   ├── answer.py
│   │   ├── __init__.py
├── infrastructure
│   ├── asgi.py
│   │       ...
│   ├── urls.py
│   └── wsgi.py
├──settings
...
│   ├── apps.py
│   ├── files.py
│   ├── __init__.py
│   ├── logging.py
│   ├── main.py
│   ├── middlewares.py
...
├── manage.py
...

特殊现象:执行./manage.py test modulname.tests时所有测试正常通过,Django不会把models/admin模块识别为测试用例。

相关模块的__init__.py内容:

  • settings模块:
...
from .apps import *
from .middlewares import *
from .drf import *
...
  • 测试、models等模块示例:
from .anomaly import AnomalyCreateDefaultAction, AnomalyAPITest

疑问:为何unittest会把admin类和model类识别为测试用例并尝试运行?

原因分析

Django的测试发现基于Python标准库unittest的规则:

  1. 默认情况下,unittest会递归扫描项目,除了找命名为test*.py的文件,还会把包含__init__.py的包当作潜在测试包——如果这些包的模块里有继承unittest.TestCase的类,就会被当作测试用例加载。
  2. 你的models、admin模块的__init__.py导入了类,加载时触发了Admin注册逻辑;同时,测试模块的__init__.py导入了测试类,可能通过项目的导入路径被models/admin模块间接引用到,导致unittest误判这些非测试包为测试包。
  3. 当你指定modulname.tests时,测试范围被限定到tests子包内,unittest只会扫描该路径下的内容,不会触及admin、models模块,因此不会触发错误。
解决方案
  1. 明确指定测试路径:
    日常测试直接限定测试模块,比如:

    ./manage.py test actions.tests anomalies.tests
    

    或者用通配符批量指定所有tests目录:

    ./manage.py test */tests
    
  2. 清理不必要的导入:

    • 检查models、admin模块的__init__.py,只保留必要的模型/Admin类导入,移除任何间接关联测试类的导入。
    • 测试模块的__init__.py仅导入测试相关类,避免非测试模块间接引用到测试类。
  3. 自定义测试发现规则:
    在项目根目录创建unittest.cfg文件,排除非测试目录:

    [unittest]
    discover = True
    pattern = test*.py
    top_level_dir = .
    exclude = admin models
    

    执行测试时指定配置文件:

    ./manage.py test --config=unittest.cfg
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:50:33