1

编辑:这是一个便于测试的 git repo:

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 文件中重用?

4

2 回答 2

1

is_ugit_dir将夹具的范围更改"session"为评论中建议的就足够了;其余的都是您自己的代码中的错误:

  1. 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夹具的返回必须更改为objects_dir / sha_hashpathlib路径一起使用。

  2. contents = f.read()
    with open(file_path, "rb") as hf:
        assert hf.read() == f.read()
    

    除了file_path没有定义(我想这应该是file_within_ugit_dir)之外,您正在将文件读入contents然后再次。为什么?f.seek(0)在再次调用之前通过回退文件f.read()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
于 2020-12-20T21:46:07.443 回答
0

我会说你的代码中有逻辑问题。根据测试场景,fixture file_hashed必须返回包含哈希的现有文件的路径。可以在这里看到:

@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中,您没有创建包含哈希的文件。相反,您正在创建一个虚拟链接,并且由于该链接上没有任何内容,因此您会收到 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
于 2020-12-19T20:41:27.037 回答