如何在多测试用例中对sys.argv进行单元测试
问题原因
Python的模块导入机制会将已导入的模块缓存到sys.modules字典中。第一次import example时,模块顶层代码会执行,ex1和ex2被赋值为当时sys.argv的对应值;第二次import example时,Python直接从缓存中取出已加载的模块,不会重新执行顶层代码,所以即便你patch了新的sys.argv,也不会更新ex1和ex2的值。
解决方案
有两种可行的修改方式:
方案1:测试时移除模块缓存
在每个测试用例结束后,从sys.modules中删除example模块,这样下次import会重新加载模块并执行顶层代码。修改后的测试代码如下:
import unittest import mock import sys class TestExample(unittest.TestCase): @mock.patch.object(sys, 'argv', ['test1', 'Test1']) def test_example1(self): import example # 测试后移除模块缓存 del sys.modules['example'] @mock.patch.object(sys, 'argv', ['test2', 'Test2']) def test_example2(self): import example del sys.modules['example']
方案2:重构业务代码,将逻辑封装为函数
更合理的做法是把读取sys.argv的逻辑封装到函数中,每次调用函数时都会重新读取当前的sys.argv值。
修改后的example.py:
import sys def print_args(): ex1 = sys.argv[0] ex2 = sys.argv[1] print(ex1) print(ex2) # 保留原有的执行逻辑,避免影响正常使用 if __name__ == "__main__": print_args()
对应的测试代码:
import unittest import mock import sys import example class TestExample(unittest.TestCase): @mock.patch.object(sys, 'argv', ['test1', 'Test1']) def test_example1(self): example.print_args() @mock.patch.object(sys, 'argv', ['test2', 'Test2']) def test_example2(self): example.print_args()
这种方式更符合Python代码组织规范,也让测试更灵活。
内容的提问来源于stack exchange,提问作者pikk
相关产品推荐
相关产品推荐

