Python 我想模拟打开一个现有的测试文件,为测试应用一个函数,但不更改文件的实际内容
我有一个更新rpm规范文件以供以后使用的函数。它有三个参数:应用程序的名称、我们想要升级到的版本以及spec文件在文件系统中的位置 我似乎不能做的是,比如说,拥有一个tests/files/package_name.spec文件,并测试它是否在不更改实际spec文件的情况下正确地对其进行了版本设置。我不想更改实际的spec文件,因为它会使测试在第二次运行时变得无用 我试着查看模拟图书馆和模拟开放,但似乎没有什么适合这种情况Python 我想模拟打开一个现有的测试文件,为测试应用一个函数,但不更改文件的实际内容,python,python-3.x,unit-testing,testing,mocking,Python,Python 3.x,Unit Testing,Testing,Mocking,我有一个更新rpm规范文件以供以后使用的函数。它有三个参数:应用程序的名称、我们想要升级到的版本以及spec文件在文件系统中的位置 我似乎不能做的是,比如说,拥有一个tests/files/package_name.spec文件,并测试它是否在不更改实际spec文件的情况下正确地对其进行了版本设置。我不想更改实际的spec文件,因为它会使测试在第二次运行时变得无用 我试着查看模拟图书馆和模拟开放,但似乎没有什么适合这种情况 def test_update_spec_file(): upd
def test_update_spec_file():
update_spec_file("package_name", "5.0.0", "files/package_name")
with open("files/package_name.spec", "r") as f:
contents = f.read()
version_regex = re.compile("^.*define _software_version.*$")
assert (
re.search(version_regex, contents).group(0)
== "%define _software_version 5.0.0"
)
基本上,update\u spec\u file
函数所做的是使用regex查找%define\u software\u version 5.0.0
行,并再次使用regex在新版本中进行sub
总之,是否有可能让文件存在,用某种模拟文件及其内容打开它,在该文件上运行函数,并断言它完成了它的工作,而不实际修改文件系统中的文件
或者在修改文件后重置该文件
以下是更新等级库文件的代码:
def update_spec_file(application, release_version, path_to_spec_file):
"""Update the spec file with the release version.
Args:
application (str): Name of the application.
release_version (str): New version of application.
path_to_spec_file (str, optional):
path the the applications spec file we are modifying.
"""
print(f"Updating spec file _software_version to {release_version}")
try:
with open(path_to_spec_file, "r") as spec_file:
spec_contents = spec_file.readlines()
except EnvironmentError:
print(f"Unable to open spec file located at: {path_to_spec_file}")
# raise the original exception again.
raise
# Find and replace software version in contents of spec file.
version_regex = re.compile("%define _software_version.*?(?=(?:\\n)|$)")
define_version = f"%define _software_version {release_version}"
# Splice the new software version line into the existing file contents
spec_contents[:] = [
version_regex.sub(define_version, line) for line in spec_contents
]
try: # Open the file and write the new spliced contents
with open(path_to_spec_file, "w") as f_spec_file:
f_spec_file.writelines(spec_contents)
except EnvironmentError: # Catch spec file not found.
print(f"Unable to open spec file located at: {path_to_spec_file}")
# raise the original exception again.
raise
编辑:
这是修改后的代码:
def test_update_spec_file():
content = open("tests/files/package_name.spec").read()
with patch(__name__ + ".open", create=True) as mock_open:
mock_open.return_value.__enter__.return_value = StringIO(content)
with open("tests/files/package_name.spec") as f:
update_spec_file(
"package_name", "5.0.0", "tests/files/package_name.spec"
我要做的是在测试运行之前测试规范文件,在测试运行之后测试规范文件
代码的树结构:
release/
├── release_all_in_one
│ ├── changelog_utils.py
│ ├── confluence_email.py
│ ├── confluence_utils.py
│ ├── create_confluence_page.py
│ ├── __init__.py
│ ├── jira_utils.py
│ ├── parse_confluence.py
│ ├── parse_rm_objects.py
│ ├── release_all_in_one_openshift.py
│ ├── release_all_in_one.py
│ ├── tag_branch.py
│ ├── templates
│ │ ├── admin_package_template
│ │ ├── base_template
│ │ ├── cdn_package_template
│ │ ├── fe_package_template
│ │ ├── oddjob_package_template
│ │ ├── openshift_template
│ │ └── procedure.json
│ └── utils.py
├── setup.cfg
├── setup.py
└── tests
├── files
│ └── package_name.spec
├── test_changelog.py
├── testing_utils.py
└── test_utils.py
您可以
patch
使用open
函数返回上下文管理器,该上下文管理器返回带有实际文件内容的io.StringIO
对象:
from unittest.mock import patch
from io import StringIO
content = '123' # value for demo
# uncomment the line below to read actual file content
# content = open('files/package_name.spec').read()
with patch(__name__ + '.open', create=True) as mock_open:
mock_open.return_value.__enter__.return_value = StringIO(content)
with open('files/package_name.spec') as f:
print(f.read())
f.seek(0)
f.write('abc')
f.seek(0)
print(f.read())
这将产生:
123
abc
或者,您可以将open
指定给MagicMock
对象,以便覆盖同一模块中对open
的所有引用:
from unittest.mock import MagicMock
from io import StringIO
content = '123' # value for demo
# uncomment the line below to read actual file content
# content = open('files/package_name.spec').read()
open = MagicMock()
open.return_value.__enter__.return_value = StringIO(content)
with open('files/package_name.spec') as f:
print(f.read())
f.seek(0)
f.write('abc')
f.seek(0)
print(f.read())
嘿,我很感谢您的帮助,但是这仍然会修改实际文件:\n请使用实际代码更新您的问题,以更新文件。当前发布的代码根本不修改文件。在其中添加了函数。我将尝试。它在同一模块中。我可以很快发布树结构。好的,这确实有效。谢谢你一直以来的帮助。