无法通过tox.ini运行unittest测试,遇模块缺失等问题
问题描述
我使用unittest库编写单元测试用例,结合mock实现测试逻辑,配置tox.ini运行测试时,先后遇到两个问题:
- 测试用例收集为0,无测试执行
- 解决收集问题后,触发
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
相关产品推荐
相关产品推荐

