Pytest未执行包模块代码求助(基于《笨办法学Python》)
Pytest运行包测试时模块代码执行异常问题
问题情况
正在学习《笨办法学Python》练习46,搭建项目骨架并使用Pytest测试代码时遇到以下问题:
- 运行整个包的测试时,测试显示通过,但模块代码未按预期重复执行(仅在单独运行
test_Dandy2.py时模块代码会完整运行) - 尝试在包目录的
__init__.py中写入import Dandy2,触发ImportError - 怀疑是Windows+PowerShell环境配置问题(此前需修改执行策略才能运行脚本),但测试能通过、单独运行模块正常,不确定是否属于正常行为
项目目录结构
project_1\ bin\ docs\ project1\ __init__.py Dandy2.py tests\ __init__.py test_project1.py test_Dandy2.py setup.py
PowerShell运行输出
(lpthw) PS C:\Users\desou\OneDrive\Desktop\venvs\projects\project_1> python -m pytest -s ============================================== test session starts =============================================== platform win32 -- Python 3.12.2, pytest-8.0.2, pluggy-1.4.0 rootdir: C:\Users\desou\OneDrive\Desktop\venvs\projects\project_1 collecting ... Hello this is a test program. You will be tested, how much is 77 + 33? \> 4 Test complete. You've proved that you lack math skills. collected 2 items tests\test_Dandy2.py SETUP! I RAN! .TEAR DOWN! tests\test_project1.py SETUP! I RAN! .TEAR DOWN! =============================================== 2 passed in 2.22s ===============================================
模块代码(Dandy2.py)
print("Hello this is a test program.") print("You will be tested, how much is 77 + 33?") x = input("> ") if x != '110': print("Test complete. You've proved that you lack math skills.") pass else: print("Test complete. Congratulations, you have a brain.") pass
原因分析
- 模块代码执行时机问题:从运行输出看,模块的打印内容在
collecting阶段已经出现,说明模块在Pytest收集测试用例时被导入,顶层代码已经执行。你觉得“未执行”可能是误解——顶层代码仅在模块导入时运行一次,若测试用例中没有显式调用模块逻辑,不会重复执行。 - init.py导入错误:在包内直接写
import Dandy2属于绝对导入,Python会从sys.path中查找该模块,而此时包目录未被识别为路径的一部分,需用相对导入from . import Dandy2才能正确导入同包内的模块。 - 测试代码逻辑问题:若你的测试用例仅做简单断言、未调用模块中的逻辑,自然不会触发模块代码的再次执行;单独运行
test_Dandy2.py时模块代码运行,是因为单独运行时模块被重新导入,顶层代码再次执行。
解决步骤
1. 修正包内导入方式
修改project1/__init__.py的内容为:
from . import Dandy2
这样就能正确导入同目录下的Dandy2模块,避免ImportError。
2. 让测试用例主动触发模块逻辑
由于当前模块代码都是顶层代码,仅在导入时执行。若想在测试过程中多次执行模块逻辑,需将代码封装成函数:
修改Dandy2.py:
def run_test(): print("Hello this is a test program.") print("You will be tested, how much is 77 + 33?") x = input("> ") if x != '110': print("Test complete. You've proved that you lack math skills.") else: print("Test complete. Congratulations, you have a brain.") # 单独运行模块时执行 if __name__ == "__main__": run_test()
然后在test_Dandy2.py中导入并调用该函数:
from project1 import Dandy2 def test_dandy2(): # 调用模块中的测试逻辑 Dandy2.run_test() # 可添加断言逻辑验证结果
3. 确保Pytest能正确识别模块
使用python -m pytest命令运行测试时,项目根目录会自动被加入Python的sys.path,因此from project1 import Dandy2这种绝对导入方式是可行的,无需额外配置PATH。
内容的提问来源于stack exchange,提问作者H. Leoni de Souza
相关产品推荐
相关产品推荐

