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

无法通过tox.ini运行unittest测试,遇模块缺失等问题

问题描述

我使用unittest库编写单元测试用例,结合mock实现测试逻辑,配置tox.ini运行测试时,先后遇到两个问题:

  1. 测试用例收集为0,无测试执行
  2. 解决收集问题后,触发ModuleNotFoundError: No module named 'mock'错误

以下是相关代码、配置、错误日志及项目结构:

测试代码

from services.snowflake_api import SnowflakeApi
from unittest import TestCase
from mock import patch


class SnowflakeDbTest(TestCase):

    @patch('services.SnowflakeAPI.snowflake.connector')  # 配置数据库对象的装饰器
    def test_get_database_connection(self, mock_connection):
        mock_connection.connect.return_value = "dbconnection"  # 设置调用数据库连接方法后返回的mock值
        self.assertEqual("dbconnection",
                         SnowflakeApi.get_database_connection("user", "password", "account", "warehouse",
                                                              database=None, schema=None))

tox.ini配置

[tox]
envlist = py310

[testenv]
deps = pytest
commands = pytest

错误日志1(收集0用例)

/Users/abc/IdeaProjects/python_project/venv/bin/python /Users/abc/Library/Application Support/JetBrains/IdeaIC2022.2/plugins/python-ce/helpers/pycharm/_jb_tox_runner.py 
Testing started at 8:24 pm ...
GLOB sdist-make: /Users/abc/IdeaProjects/project/abc/module/setup.py
py310 inst-nodeps: /Users/abc/IdeaProjects/project/abc/module/.tox/.tmp/package/1/dm-snowflake-1.0.0.zip
WARNING: Discarding $PYTHONPATH from environment, to override specify PYTHONPATH in 'passenv' in your configuration.
py310 installed: asn1crypto==1.4.0,attrs==22.1.0,certifi==2021.10.8,cffi==1.15.0,charset-normalizer==2.0.9,cryptography==35.0.0,distlib==0.3.4,dm-snowflake==1.0.0,filelock==3.4.2,idna==3.3,iniconfig==1.1.1,oscrypto==1.2.1,packaging==21.3,platformdirs==2.4.1,pluggy==1.0.0,py==1.11.0,pycparser==2.21,pycryptodomex==3.15.0,PyJWT==2.3.0,pyOpenSSL==21.0.0,pyparsing==3.0.6,pytest==6.2.5,pytz==2021.3,requests==2.27.1,six==1.16.0,snowflake-connector-python==2.7.2,toml==0.10.2,tox==3.25.1,urllib3==1.26.7,virtualenv==20.13.2
py310 run-test-pre: PYTHONHASHSEED='2295913608'
py310 run-test: commands[0] | /Users/abc/IdeaProjects/project/abc/module/.tox/py310/bin/python '/Users/abc/Library/Application Support/JetBrains/IdeaIC2022.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py' --offset 1 --
Launching pytest with arguments --no-header --no-summary -q in /Users/abc/IdeaProjects/project/abc/module

============================= test session starts ==============================
collecting ... collected 0 items

============================ no tests ran in 0.01s =============================
ERROR: InvocationError for command /Users/abc/IdeaProjects/project/abc/module/.tox/py310/bin/python '/Users/abc/Library/Application Support/JetBrains/IdeaIC2022.2/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py' --offset 1 -- (exited with code 5)

commands failed
___________________________________ summary ____________________________________
ERROR:   py310: commands failed

Process finished with exit code 1

错误日志2(mock模块缺失)

============================= test session starts ==============================
collecting ... 
tests/snowflake/test_example_01.py:None (tests/snowflake/test_example_01.py)
ImportError while importing test module '/Users/abc/IdeaProjects/project/abc/module/tests/snowflake/test_example_01.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
.tox/py310/lib/python3.10/site-packages/_pytest/python.py:608: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
.tox/py310/lib/python3.10/site-packages/_pytest/pathlib.py:533: in import_path
    importlib.import_module(module_name)
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1050: in _gcd_import
    ???
<frozen importlib._bootstrap>:1027: in _find_and_load
    ???
<frozen importlib._bootstrap>:1006: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:688: in _load_unlocked
    ???
.tox/py310/lib/python3.10/site-packages/_pytest/assertion/rewrite.py:168: in exec_module
    exec(co, module.__dict__)
tests/snowflake/test_example_01.py:3: in <module>
    from mock import patch
E   ModuleNotFoundError: No module named 'mock'

项目结构

项目结构


错误分析与修复方案

1. 测试用例收集为0的问题

原因

  • pytest默认只识别test_*.py命名的测试文件,以及文件内test_*命名的测试方法,若文件名不符合规则则无法被收集
  • tox默认会打包安装项目,测试代码不在打包范围内,导致虚拟环境中找不到测试文件
  • tox运行时未指定测试目录,且丢弃了PYTHONPATH,导致无法定位到测试代码和项目源码

修复

修改tox.ini配置,确保测试代码可被找到,同时保留路径信息:

[tox]
envlist = py310

[testenv]
deps = 
    pytest
    mock
commands = pytest tests/  # 指定测试目录路径
passenv = PYTHONPATH  # 保留系统PYTHONPATH,确保能找到项目模块
usedevelop = true  # 开发模式安装项目,不打包,直接映射源码路径

同时确认测试文件命名符合test_*.py规则。

2. ModuleNotFoundError: No module named 'mock'的问题

原因

  • Python 3.3+版本中,mock已整合到标准库unittest.mock中,无需单独安装;若代码中仍从mock导入则会报错
  • 若使用老旧pytest版本,可能需单独安装mock包兼容

修复

方案1(推荐,标准库方式)

修改测试代码的导入语句,改用标准库模块:

from services.snowflake_api import SnowflakeApi
from unittest import TestCase
from unittest.mock import patch  # 替换原from mock import patch

方案2(兼容老版本)

在tox.ini的依赖中添加mock包:

[testenv]
deps = 
    pytest
    mock

额外注意点

  • @patch装饰器中的路径services.SnowflakeAPI.snowflake.connector存在大小写问题:测试代码导入的是SnowflakeApi(小写结尾),但patch路径写的是SnowflakeAPI(大写结尾),需与实际模块中的类名保持一致,否则mock不会生效
  • 确保services模块在Python路径中,tox配置的usedevelop = true会自动将项目根目录加入路径,解决模块导入问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 06:10:39