首页 > 解决方案 > 使用 unittest.mock 时 Python 覆盖率崩溃

问题描述

我有一个 Python 库,我正在其中设置一些测试。作为测试的一部分,我使用 MagicMock 来模拟一些功能,例如 JSON 加载和文件打开和关闭。测试工作,一切都按预期工作。

当我尝试使用覆盖率运行测试时,问题就出现了。由于我介绍了使用模拟的新测试,因此覆盖率崩溃了。

这是我实现模拟的部分:

def setUp(self):
    # Setup the content of the config files for the tests
    json.load = MagicMock(side_effect=file_content)

    # Opening a file returns the name of the file
    def get_mock_context(filename):
        mock_context = MagicMock()
        mock_context.__enter__.return_value = filename
        mock_context.__exit__.return_value = False
        return mock_context
    builtins.open = MagicMock(side_effect=get_mock_context)

如前所述,当我运行测试时,一切似乎都运行良好

python -m unittest discover -s tests -p "*Tests.py"   
...........................
----------------------------------------------------------------------
Ran 27 tests in 1.322s

OK

尽管如此,一旦我介绍了覆盖范围:

coverage run -m unittest discover -s tests -p "*Tests.py"
...........................
----------------------------------------------------------------------
Ran 27 tests in 1.759s

OK
Traceback (most recent call last):
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 627, in do_run
    self.run_python_module(args[0], args)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/execfile.py", line 122, in run_python_module
    run_python_file(pathname, args, package=packagename, modulename=modulename, path0=path0)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/execfile.py", line 192, in run_python_file
    exec(code, main_mod.__dict__)
  File "/anaconda3/envs/c360/lib/python3.7/unittest/__main__.py", line 18, in <module>
    main(module=None)
  File "/anaconda3/envs/c360/lib/python3.7/unittest/main.py", line 101, in __init__
    self.runTests()
  File "/anaconda3/envs/c360/lib/python3.7/unittest/main.py", line 273, in runTests
    sys.exit(not self.result.wasSuccessful())
SystemExit: False

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/anaconda3/envs/c360/bin/coverage", line 10, in <module>
    sys.exit(main())
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 756, in main
    status = CoverageScript().command_line(argv)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 491, in command_line
    return self.do_run(options, args)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 641, in do_run
    self.coverage.save()
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/control.py", line 782, in save
    self.data_files.write(self.data, suffix=self.data_suffix)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/data.py", line 680, in write
    data.write_file(filename)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/data.py", line 467, in write_file
    with open(filename, 'w') as fdata:
  File "/anaconda3/envs/c360/lib/python3.7/unittest/mock.py", line 951, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/anaconda3/envs/c360/lib/python3.7/unittest/mock.py", line 1017, in _mock_call
    result = effect(*args, **kwargs)
TypeError: get_mock_context() takes 1 positional argument but 2 were given

我不知道问题可能是什么。我已经尝试排除测试文件中包含模拟pragma: no cover但没有做任何事情的行。我找不到让这项工作再次发挥作用的方法。有什么想法或你认为我可能错过的东西吗?

编辑:

我刚刚清理了一些之前粘贴的代码。如果我运行覆盖指定我只想将本地目录中的文件用作源(以避免在 python 库等中使用覆盖),我会收到以下错误。仍然不工作,但不同的:

Traceback (most recent call last):
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 627, in do_run
    self.run_python_module(args[0], args)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/execfile.py", line 122, in run_python_module
    run_python_file(pathname, args, package=packagename, modulename=modulename, path0=path0)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/execfile.py", line 192, in run_python_file
    exec(code, main_mod.__dict__)
  File "/anaconda3/envs/c360/lib/python3.7/unittest/__main__.py", line 18, in <module>
    main(module=None)
  File "/anaconda3/envs/c360/lib/python3.7/unittest/main.py", line 101, in __init__
    self.runTests()
  File "/anaconda3/envs/c360/lib/python3.7/unittest/main.py", line 273, in runTests
    sys.exit(not self.result.wasSuccessful())
SystemExit: False

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/anaconda3/envs/c360/bin/coverage", line 10, in <module>
    sys.exit(main())
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 756, in main
    status = CoverageScript().command_line(argv)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 491, in command_line
    return self.do_run(options, args)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/cmdline.py", line 641, in do_run
    self.coverage.save()
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/control.py", line 781, in save
    self.get_data()
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/control.py", line 834, in get_data
    self._post_save_work()
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/control.py", line 864, in _post_save_work
    self._find_unexecuted_files(src)
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/control.py", line 913, in _find_unexecuted_files
    for file_path, plugin_name in itertools.chain(py_files, plugin_files):
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/control.py", line 910, in <genexpr>
    py_files = ((py_file, None) for py_file in find_python_files(src_dir))
  File "/anaconda3/envs/c360/lib/python3.7/site-packages/coverage/files.py", line 416, in find_python_files
    del dirnames[:]
TypeError: 'tuple' object does not support item deletion

标签: pythonunit-testingmockingcode-coverage

解决方案


推荐阅读