使用 tmp_path fixture 创建后路径不存在
path does not exist after being created with tmp_path fixture
编辑:这是一个 git 便于测试的回购协议:
https://gitlab.com/qualisign/ugit-bdd/
我想将一些重复代码从 step_def 文件重构到 conftest.py
文件。这是 step_def 的样子:
@scenario('../features/CLI.feature',
'store file in object database')
def test_file_stored_by_content_address():
pass
@given("a file exists at some full path within a ugit dir", target_fixture="file_exists_at_path")
def file_exists_at_path(file_within_ugit_dir):
return file_within_ugit_dir
@when("I enter ugit hash-object followed by that path")
def file_gets_hashed(file_exists_at_path):
dir_name = os.path.dirname(file_exists_at_path)
base_name = os.path.basename(file_exists_at_path)
os.chdir(dir_name)
os.system(f'ugit hash-object {base_name}')
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_within_ugit_dir, file_hashed):
with open(file_hashed, "rb") as f:
contents = f.read()
with open(file_path, "rb") as hf:
assert hf.read() == f.read()
这里是 conftest.py
:
import os
import subprocess
import hashlib
import pytest
from pytest_bdd import scenario, given, when, then, parsers
WISE_WORDS = "Don\'t be a fool! I\'ll call you later."
@pytest.fixture(scope="session")
def is_ugit_dir(tmp_path_factory):
path = tmp_path_factory.mktemp('data')
os.chdir(path)
subprocess.run(['ugit', 'init'])
return path
@pytest.fixture
def file_within_ugit_dir(is_ugit_dir):
path = is_ugit_dir
full_path = f'{path}/wise_words.txt'
os.system(f'echo {WISE_WORDS} > wise_words.txt')
return full_path
@pytest.fixture
def file_hashed(is_ugit_dir, file_within_ugit_dir):
"""
Returns the full path to a hash-object within the objects database
"""
subprocess.run(['ugit', 'hash-object', file_within_ugit_dir])
# there should now be a file with a sha1 content-address in the following directory
objects_dir = os.path.dirname(is_ugit_dir)+'/.ugit/objects/'
with open(file_within_ugit_dir, "rb") as f:
# first calculate the hash
sha_hash = hashlib.sha1 (f.read()).hexdigest ()
return objects_dir+sha_hash
当我 运行 测试时,临时目录似乎没有在步骤之间保持打开状态:
t-74/.ugit/objects/7b5ee3d8d42c66048125a3937a0170ffdaf7b272'
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_hashed):
> with open(file_hashed, "rb") as f:
E FileNotFoundError: [Errno 2] No such file or directory: '/private/var/folders/m2/99x5jvw95ll6sbtgvj5md9700000gp/T/pytest-of-davidjoseph/pytest-74/.ugit/objects/7b5ee3d8d42c66048125a3937a0170ffdaf7b272'
/Users/davidjoseph/projects/ugit-bdd/tests/step_defs/test_cli.py:43: FileNotFoundError
-------------------------------------- Captured stdout call ---------------------------------------
Initialized empty ugit repository in /private/var/folders/m2/99x5jvw95ll6sbtgvj5md9700000gp/T/pytest-of-davidjoseph/pytest-74/data1/.ugit
7b5ee3d8d42c66048125a3937a0170ffdaf7b272
有什么方法可以让这个临时目录保持打开状态,以便在 conftest.py
文件中的固定装置之间重复使用,并最终在 step_def 文件中重复使用?
我会说你的代码有逻辑问题。
根据测试场景,fixture file_hashed 必须 return 包含哈希的 existing 文件的路径。可以在这里看到:
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_within_ugit_dir, file_hashed):
with open(file_hashed, "rb") as f:
contents = f.read()
with open(file_path, "rb") as hf:
assert hf.read() == f.read()
在 conftest.py 中,您没有创建包含哈希的文件。您正在创建一个虚拟 link,并且由于 link 上没有任何内容,您会得到 FileNotFoundError。错误在这里(您的代码没有创建哈希文件):
@pytest.fixture
def file_hashed(is_ugit_dir, file_within_ugit_dir):
objects_dir = os.path.dirname(is_ugit_dir)+'/.ugit/objects/'
with open(file_within_ugit_dir, "rb") as f:
# first calculate the hash
sha_hash = hashlib.sha1 (f.read()).hexdigest ()
return objects_dir+sha_hash
按照评论中的建议将 is_ugit_dir
fixture 的范围更改为 "session"
就足够了;其余都是你自己代码的错误:
-
path = tmp_path_factory.mktemp('data')
os.chdir(path)
subprocess.run(['ugit', 'init'])
您将当前工作目录更改为 /tmp/pytest-smth/data
并在其中调用 ugit init
- 我假设该工具随后会在 /tmp/pytest-smth/data/.ugit
处创建存储库元数据。稍后,您使用
objects_dir = os.path.dirname(is_ugit_dir)+'/.ugit/objects/'
创建对象目录 - 这将使您 /tmp/pytest-smth/.ugit/objects
。难怪这个目录不存在。将其更改为例如objects_dir = is_ugit_dir / '.ugit' / 'objects'
修复了第一个错误。作为后续行动,必须将 file_hashed
夹具的 return 更改为 objects_dir / sha_hash
以使用 pathlib
路径。
-
contents = f.read()
with open(file_path, "rb") as hf:
assert hf.read() == f.read()
除了 file_path
未定义(我猜这应该是 file_within_ugit_dir
),您正在将文件读入 contents
然后再读一次。为什么?在再次调用 f.read()
之前通过 f.seek(0)
倒回文件,或者使用 contents
进行比较。
这是完整的工作代码,只进行了最少的必要更改:
conftest.py
import os
import subprocess
import hashlib
import pytest
from pytest_bdd import scenario, given, when, then, parsers
WISE_WORDS = "Don\'t be a fool! I\'ll call you later."
@pytest.fixture(scope="session")
def is_ugit_dir(tmp_path_factory):
path = tmp_path_factory.mktemp('data')
os.chdir(path)
subprocess.run(['ugit', 'init'])
return path
@pytest.fixture
def file_within_ugit_dir(is_ugit_dir):
path = is_ugit_dir
full_path = path / 'wise_words.txt'
os.system(f'echo {WISE_WORDS} > wise_words.txt')
return full_path
@pytest.fixture
def file_hashed(is_ugit_dir, file_within_ugit_dir):
"""
Returns the full path to a hash-object within the objects database
"""
subprocess.run(['ugit', 'hash-object', file_within_ugit_dir])
# there should now be a file with a sha1 content-address in the following directory
objects_dir = is_ugit_dir / '.ugit' / 'objects'
with open(file_within_ugit_dir, "rb") as f:
# first calculate the hash
data = b'blob\x00' + f.read() # prepend the object type
sha_hash = hashlib.sha1(data).hexdigest()
return objects_dir / sha_hash
step_def.py
import os
from pytest_bdd import scenario, given, when, then, parsers
@scenario('features/CLI.feature', 'store file in object database')
def test_file_stored_by_content_address():
pass
@given("a file exists at some full path within a ugit dir", target_fixture="file_exists_at_path")
def file_exists_at_path(file_within_ugit_dir):
return file_within_ugit_dir
@when("I enter ugit hash-object followed by that path")
def file_gets_hashed(file_exists_at_path):
dir_name = os.path.dirname(file_exists_at_path)
base_name = os.path.basename(file_exists_at_path)
os.chdir(dir_name)
os.system(f'ugit hash-object {base_name}')
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_within_ugit_dir, file_hashed):
with open(file_hashed, "rb") as f:
contents = f.read().strip(b"blob\x00")
with open(file_within_ugit_dir, "rb") as hf:
assert hf.read() == contents
编辑:这是一个 git 便于测试的回购协议:
https://gitlab.com/qualisign/ugit-bdd/
我想将一些重复代码从 step_def 文件重构到 conftest.py
文件。这是 step_def 的样子:
@scenario('../features/CLI.feature',
'store file in object database')
def test_file_stored_by_content_address():
pass
@given("a file exists at some full path within a ugit dir", target_fixture="file_exists_at_path")
def file_exists_at_path(file_within_ugit_dir):
return file_within_ugit_dir
@when("I enter ugit hash-object followed by that path")
def file_gets_hashed(file_exists_at_path):
dir_name = os.path.dirname(file_exists_at_path)
base_name = os.path.basename(file_exists_at_path)
os.chdir(dir_name)
os.system(f'ugit hash-object {base_name}')
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_within_ugit_dir, file_hashed):
with open(file_hashed, "rb") as f:
contents = f.read()
with open(file_path, "rb") as hf:
assert hf.read() == f.read()
这里是 conftest.py
:
import os
import subprocess
import hashlib
import pytest
from pytest_bdd import scenario, given, when, then, parsers
WISE_WORDS = "Don\'t be a fool! I\'ll call you later."
@pytest.fixture(scope="session")
def is_ugit_dir(tmp_path_factory):
path = tmp_path_factory.mktemp('data')
os.chdir(path)
subprocess.run(['ugit', 'init'])
return path
@pytest.fixture
def file_within_ugit_dir(is_ugit_dir):
path = is_ugit_dir
full_path = f'{path}/wise_words.txt'
os.system(f'echo {WISE_WORDS} > wise_words.txt')
return full_path
@pytest.fixture
def file_hashed(is_ugit_dir, file_within_ugit_dir):
"""
Returns the full path to a hash-object within the objects database
"""
subprocess.run(['ugit', 'hash-object', file_within_ugit_dir])
# there should now be a file with a sha1 content-address in the following directory
objects_dir = os.path.dirname(is_ugit_dir)+'/.ugit/objects/'
with open(file_within_ugit_dir, "rb") as f:
# first calculate the hash
sha_hash = hashlib.sha1 (f.read()).hexdigest ()
return objects_dir+sha_hash
当我 运行 测试时,临时目录似乎没有在步骤之间保持打开状态:
t-74/.ugit/objects/7b5ee3d8d42c66048125a3937a0170ffdaf7b272'
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_hashed):
> with open(file_hashed, "rb") as f:
E FileNotFoundError: [Errno 2] No such file or directory: '/private/var/folders/m2/99x5jvw95ll6sbtgvj5md9700000gp/T/pytest-of-davidjoseph/pytest-74/.ugit/objects/7b5ee3d8d42c66048125a3937a0170ffdaf7b272'
/Users/davidjoseph/projects/ugit-bdd/tests/step_defs/test_cli.py:43: FileNotFoundError
-------------------------------------- Captured stdout call ---------------------------------------
Initialized empty ugit repository in /private/var/folders/m2/99x5jvw95ll6sbtgvj5md9700000gp/T/pytest-of-davidjoseph/pytest-74/data1/.ugit
7b5ee3d8d42c66048125a3937a0170ffdaf7b272
有什么方法可以让这个临时目录保持打开状态,以便在 conftest.py
文件中的固定装置之间重复使用,并最终在 step_def 文件中重复使用?
我会说你的代码有逻辑问题。 根据测试场景,fixture file_hashed 必须 return 包含哈希的 existing 文件的路径。可以在这里看到:
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_within_ugit_dir, file_hashed):
with open(file_hashed, "rb") as f:
contents = f.read()
with open(file_path, "rb") as hf:
assert hf.read() == f.read()
在 conftest.py 中,您没有创建包含哈希的文件。您正在创建一个虚拟 link,并且由于 link 上没有任何内容,您会得到 FileNotFoundError。错误在这里(您的代码没有创建哈希文件):
@pytest.fixture
def file_hashed(is_ugit_dir, file_within_ugit_dir):
objects_dir = os.path.dirname(is_ugit_dir)+'/.ugit/objects/'
with open(file_within_ugit_dir, "rb") as f:
# first calculate the hash
sha_hash = hashlib.sha1 (f.read()).hexdigest ()
return objects_dir+sha_hash
按照评论中的建议将 is_ugit_dir
fixture 的范围更改为 "session"
就足够了;其余都是你自己代码的错误:
-
path = tmp_path_factory.mktemp('data') os.chdir(path) subprocess.run(['ugit', 'init'])
您将当前工作目录更改为
/tmp/pytest-smth/data
并在其中调用ugit init
- 我假设该工具随后会在/tmp/pytest-smth/data/.ugit
处创建存储库元数据。稍后,您使用objects_dir = os.path.dirname(is_ugit_dir)+'/.ugit/objects/'
创建对象目录 - 这将使您
/tmp/pytest-smth/.ugit/objects
。难怪这个目录不存在。将其更改为例如objects_dir = is_ugit_dir / '.ugit' / 'objects'
修复了第一个错误。作为后续行动,必须将file_hashed
夹具的 return 更改为objects_dir / sha_hash
以使用pathlib
路径。 -
contents = f.read() with open(file_path, "rb") as hf: assert hf.read() == f.read()
除了
file_path
未定义(我猜这应该是file_within_ugit_dir
),您正在将文件读入contents
然后再读一次。为什么?在再次调用f.read()
之前通过f.seek(0)
倒回文件,或者使用contents
进行比较。
这是完整的工作代码,只进行了最少的必要更改:
conftest.py
import os
import subprocess
import hashlib
import pytest
from pytest_bdd import scenario, given, when, then, parsers
WISE_WORDS = "Don\'t be a fool! I\'ll call you later."
@pytest.fixture(scope="session")
def is_ugit_dir(tmp_path_factory):
path = tmp_path_factory.mktemp('data')
os.chdir(path)
subprocess.run(['ugit', 'init'])
return path
@pytest.fixture
def file_within_ugit_dir(is_ugit_dir):
path = is_ugit_dir
full_path = path / 'wise_words.txt'
os.system(f'echo {WISE_WORDS} > wise_words.txt')
return full_path
@pytest.fixture
def file_hashed(is_ugit_dir, file_within_ugit_dir):
"""
Returns the full path to a hash-object within the objects database
"""
subprocess.run(['ugit', 'hash-object', file_within_ugit_dir])
# there should now be a file with a sha1 content-address in the following directory
objects_dir = is_ugit_dir / '.ugit' / 'objects'
with open(file_within_ugit_dir, "rb") as f:
# first calculate the hash
data = b'blob\x00' + f.read() # prepend the object type
sha_hash = hashlib.sha1(data).hexdigest()
return objects_dir / sha_hash
step_def.py
import os
from pytest_bdd import scenario, given, when, then, parsers
@scenario('features/CLI.feature', 'store file in object database')
def test_file_stored_by_content_address():
pass
@given("a file exists at some full path within a ugit dir", target_fixture="file_exists_at_path")
def file_exists_at_path(file_within_ugit_dir):
return file_within_ugit_dir
@when("I enter ugit hash-object followed by that path")
def file_gets_hashed(file_exists_at_path):
dir_name = os.path.dirname(file_exists_at_path)
base_name = os.path.basename(file_exists_at_path)
os.chdir(dir_name)
os.system(f'ugit hash-object {base_name}')
@then("this object is stored in a content-addressed location in the subdirectory .ugit/objects")
def object_saved_in_db(file_within_ugit_dir, file_hashed):
with open(file_hashed, "rb") as f:
contents = f.read().strip(b"blob\x00")
with open(file_within_ugit_dir, "rb") as hf:
assert hf.read() == contents