通过Python Invoke任务执行unittest测试报错,求解决方案
我之前也碰到过类似的情况,你的问题本质是**unittest.main()在Invoke任务上下文里会错误解析命令行参数**导致的,咱们一步步拆解清楚:
错误原因分析
当你用inv tests执行任务时,Invoke会修改当前进程的sys.argv,把它变成类似['tasks.py', 'tests']这样的参数。而unittest.main()默认会读取sys.argv来确定要运行的测试目标——它误以为你要运行my_tests模块里名为tests的测试对象,但你的测试类是TestStringMethods,自然找不到对应属性,就抛出了AttributeError: module 'my_tests' has no attribute 'tests'。
而直接运行my_tests.py或tasks.py时,sys.argv里没有额外的Invoke任务参数,unittest.main()能正确识别并加载所有测试用例,所以一切正常。
解决方案
这里有两种靠谱的解决办法,选你顺手的就行:
方法1:手动指定unittest的argv参数
修改tasks.py里的main函数,显式传递argv参数,不让unittest读取Invoke的命令行参数:
def main(): import my_tests import unittest # 手动指定argv,只传递模块名,避免解析Invoke的任务参数 unittest.main(module='my_tests', argv=['my_tests'])
这样unittest.main()就会忽略掉Invoke的参数,正确加载my_tests里的所有测试用例。
方法2:直接用Invoke执行unittest命令(更推荐)
其实没必要在代码里调用unittest.main(),直接让Invoke通过shell命令运行unittest更简单,也避免了上下文参数的干扰:
修改tasks.py里的tests任务:
@task def tests(ctx): # 用ctx.run执行unittest命令,pty=True让输出格式更友好 ctx.run("python -m unittest my_tests", pty=True)
这种方式和你直接在命令行运行python -m unittest my_tests效果完全一致,而且更符合Invoke的使用习惯。
验证
修改完之后,再运行inv tests,应该就能看到和直接运行时一样的测试通过输出了。
内容的提问来源于stack exchange,提问作者slo

