如何为 GitPython clone/pull 函数编写单元测试?
How to write unit tests for GitPython clone/pull functions?
我有一个 python 项目,它使用 GitPython 对远程 Git 存储库执行克隆和拉取功能。
举个简单的例子:
import git
from git import Git
from git import Repo
def clone_and_checkout(full_dir, git_url, repo_ver):
repo = Repo.clone_from(
url=git_url,
to_path=full_dir
)
# Trigger re-create if repository is bare
if repo.bare:
raise git.exc.InvalidGitRepositoryError
# Set origin and pull
origin = repo.remotes.origin
origin.pull()
# Check out desired version of repository
g = Git(full_dir)
g.checkout(repo_ver)
我希望能够为此功能编写单元测试,但显然这需要接触到当前的外部系统。
我很好奇是否有人有模拟这种外部交互的经验,其方式类似于使用 Mock 模拟 HTTP 调用。我希望能够以一种可以在测试时模拟的方式执行这些任务,而无需调用实际的 Git 远程。
我应该如何为此编写测试?
编辑:为了更清楚地说明我在问什么,我应该提到我是 Mock 的新手,并且正在努力了解如何模拟这些 类 而不是 类 本身。我的问题应该用更好的措辞来表达——类似于 "how do I use Mock to set instance-specific properties like bare?"
从那以后,我了解了很多关于 Mock 的知识,并且弄清楚了如何做到这一点,所以我将提供我自己的问题的答案。
这似乎是对 Mock 理解不完整或使用 Patch 方法的常见结果。
首先要做的是阅读 Mock 文档中的“where to patch”部分。有了这些信息,您应该能够使用 patch 函数来模拟上面函数中使用的 GitPython 对象。这些装饰器将出现在您的单元测试函数之上。
@mock.patch('gitter.Repo')
@mock.patch('gitter.Git')
为了为这些模拟对象之一的实例提供 return 值,您可以使用 PropertyMock。这是利用此功能的单元测试的完整示例:
import gitter # file containing our clone function
import mock
import unittest
class test_gitter(unittest.TestCase):
@mock.patch('gitter.Repo')
@mock.patch('gitter.Git')
def runTest(self, mock_git, mock_repo):
# Set the "bare" attribute of the Repo instance to be False
p = mock.PropertyMock(return_value=False)
type(mock_repo.clone_from.return_value).bare = p
gitter.clone_and_checkout(
'/tmp/docker',
'git@github.com:docker/docker.git',
'master'
)
mock_git.checkout.called_once_with('master')
我有一个 python 项目,它使用 GitPython 对远程 Git 存储库执行克隆和拉取功能。
举个简单的例子:
import git
from git import Git
from git import Repo
def clone_and_checkout(full_dir, git_url, repo_ver):
repo = Repo.clone_from(
url=git_url,
to_path=full_dir
)
# Trigger re-create if repository is bare
if repo.bare:
raise git.exc.InvalidGitRepositoryError
# Set origin and pull
origin = repo.remotes.origin
origin.pull()
# Check out desired version of repository
g = Git(full_dir)
g.checkout(repo_ver)
我希望能够为此功能编写单元测试,但显然这需要接触到当前的外部系统。
我很好奇是否有人有模拟这种外部交互的经验,其方式类似于使用 Mock 模拟 HTTP 调用。我希望能够以一种可以在测试时模拟的方式执行这些任务,而无需调用实际的 Git 远程。
我应该如何为此编写测试?
编辑:为了更清楚地说明我在问什么,我应该提到我是 Mock 的新手,并且正在努力了解如何模拟这些 类 而不是 类 本身。我的问题应该用更好的措辞来表达——类似于 "how do I use Mock to set instance-specific properties like bare?"
从那以后,我了解了很多关于 Mock 的知识,并且弄清楚了如何做到这一点,所以我将提供我自己的问题的答案。
这似乎是对 Mock 理解不完整或使用 Patch 方法的常见结果。
首先要做的是阅读 Mock 文档中的“where to patch”部分。有了这些信息,您应该能够使用 patch 函数来模拟上面函数中使用的 GitPython 对象。这些装饰器将出现在您的单元测试函数之上。
@mock.patch('gitter.Repo')
@mock.patch('gitter.Git')
为了为这些模拟对象之一的实例提供 return 值,您可以使用 PropertyMock。这是利用此功能的单元测试的完整示例:
import gitter # file containing our clone function
import mock
import unittest
class test_gitter(unittest.TestCase):
@mock.patch('gitter.Repo')
@mock.patch('gitter.Git')
def runTest(self, mock_git, mock_repo):
# Set the "bare" attribute of the Repo instance to be False
p = mock.PropertyMock(return_value=False)
type(mock_repo.clone_from.return_value).bare = p
gitter.clone_and_checkout(
'/tmp/docker',
'git@github.com:docker/docker.git',
'master'
)
mock_git.checkout.called_once_with('master')