summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--test/git/test_base.py29
-rw-r--r--test/git/test_blob.py12
-rw-r--r--test/git/test_commit.py28
-rw-r--r--test/git/test_config.py4
-rw-r--r--test/git/test_diff.py14
-rw-r--r--test/git/test_git.py8
-rw-r--r--test/git/test_head.py8
-rw-r--r--test/git/test_index.py18
-rw-r--r--test/git/test_performance.py6
-rw-r--r--test/git/test_remote.py27
-rw-r--r--test/git/test_repo.py88
-rw-r--r--test/git/test_stats.py6
-rw-r--r--test/git/test_tag.py8
-rw-r--r--test/testlib/__init__.py1
-rw-r--r--test/testlib/helper.py118
16 files changed, 246 insertions, 135 deletions
diff --git a/CHANGES b/CHANGES
index 377d7e07..3b42095e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -138,6 +138,12 @@ Remote
* Repo.remotes lists all remotes
* Repo.remote returns a remote of the specified name if it exists
+Test Framework
+--------------
+* Added support for common TestCase base class that provides additional functionality
+ to receive repositories tests can also write to. This way, more aspects can be
+ tested under real-world ( un-mocked ) conditions.
+
Tree
----
* former 'name' member renamed to path as it suits the actual data better
diff --git a/test/git/test_base.py b/test/git/test_base.py
index b93e61c1..a7ef9374 100644
--- a/test/git/test_base.py
+++ b/test/git/test_base.py
@@ -14,16 +14,13 @@ from itertools import chain
from git.objects.utils import get_object_type_by_name
import tempfile
-class TestBase(object):
+class TestBase(TestBase):
type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070"),
("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79"),
("commit", "4251bd59fb8e11e40c40548cba38180a9536118c"),
("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10") )
- def setup(self):
- self.repo = Repo(GIT_REPO)
-
def test_base_object(self):
# test interface of base object classes
types = (Blob, Tree, Commit, TagObject)
@@ -33,7 +30,7 @@ class TestBase(object):
num_objs = 0
num_index_objs = 0
for obj_type, (typename, hexsha) in zip(types, self.type_tuples):
- item = obj_type(self.repo,hexsha)
+ item = obj_type(self.rorepo,hexsha)
num_objs += 1
assert item.id == hexsha
assert item.type == typename
@@ -74,7 +71,7 @@ class TestBase(object):
# tag refs can point to tag objects or to commits
s = set()
ref_count = 0
- for ref in chain(self.repo.tags, self.repo.heads):
+ for ref in chain(self.rorepo.tags, self.rorepo.heads):
ref_count += 1
assert isinstance(ref, refs.Reference)
assert str(ref) == ref.name
@@ -88,7 +85,7 @@ class TestBase(object):
def test_heads(self):
# see how it dynmically updates its object
- for head in self.repo.heads:
+ for head in self.rorepo.heads:
head.name
head.path
prev_object = head.object
@@ -106,4 +103,20 @@ class TestBase(object):
def test_object_resolution(self):
# objects must be resolved to shas so they compare equal
- assert self.repo.head.object == self.repo.active_branch.object
+ assert self.rorepo.head.object == self.rorepo.active_branch.object
+
+ @with_bare_rw_repo
+ def test_with_bare_rw_repo(self, bare_rw_repo):
+ assert bare_rw_repo.config_reader("repository").getboolean("core", "bare")
+ assert os.path.isfile(os.path.join(bare_rw_repo.path,'HEAD'))
+
+ @with_rw_repo('0.1.6')
+ def test_with_rw_repo(self, rw_repo):
+ assert not rw_repo.config_reader("repository").getboolean("core", "bare")
+ assert os.path.isdir(os.path.join(rw_repo.git.git_dir,'lib'))
+
+ @with_rw_and_rw_remote_repo('0.1.6')
+ def test_with_rw_remote_and_rw_repo(self, rw_repo, rw_remote_repo):
+ assert not rw_repo.config_reader("repository").getboolean("core", "bare")
+ assert rw_remote_repo.config_reader("repository").getboolean("core", "bare")
+ assert os.path.isdir(os.path.join(rw_repo.git.git_dir,'lib'))
diff --git a/test/git/test_blob.py b/test/git/test_blob.py
index e151b3c8..1b3b68f8 100644
--- a/test/git/test_blob.py
+++ b/test/git/test_blob.py
@@ -7,26 +7,24 @@
from test.testlib import *
from git import *
-class TestBlob(object):
- def setup(self):
- self.repo = Repo(GIT_REPO)
+class TestBlob(TestBase):
def test_should_cache_data(self):
bid = 'a802c139d4767c89dcad79d836d05f7004d39aac'
- blob = Blob(self.repo, bid)
+ blob = Blob(self.rorepo, bid)
blob.data
assert blob.data
blob.size
blob.size
def test_mime_type_should_return_mime_type_for_known_types(self):
- blob = Blob(self.repo, **{'id': 'abc', 'path': 'foo.png'})
+ blob = Blob(self.rorepo, **{'id': 'abc', 'path': 'foo.png'})
assert_equal("image/png", blob.mime_type)
def test_mime_type_should_return_text_plain_for_unknown_types(self):
- blob = Blob(self.repo, **{'id': 'abc','path': 'something'})
+ blob = Blob(self.rorepo, **{'id': 'abc','path': 'something'})
assert_equal("text/plain", blob.mime_type)
def test_should_return_appropriate_representation(self):
- blob = Blob(self.repo, **{'id': 'abc'})
+ blob = Blob(self.rorepo, **{'id': 'abc'})
assert_equal('<git.Blob "abc">', repr(blob))
diff --git a/test/git/test_commit.py b/test/git/test_commit.py
index 3d7feb6d..1a74593d 100644
--- a/test/git/test_commit.py
+++ b/test/git/test_commit.py
@@ -7,13 +7,11 @@
from test.testlib import *
from git import *
-class TestCommit(object):
- def setup(self):
- self.repo = Repo(GIT_REPO)
+class TestCommit(TestBase):
def test_bake(self):
- commit = Commit(self.repo, **{'id': '2454ae89983a4496a445ce347d7a41c0bb0ea7ae'})
+ commit = Commit(self.rorepo, **{'id': '2454ae89983a4496a445ce347d7a41c0bb0ea7ae'})
commit.author # bake
assert_equal("Sebastian Thiel", commit.author.name)
@@ -21,7 +19,7 @@ class TestCommit(object):
def test_stats(self):
- commit = Commit(self.repo, id='33ebe7acec14b25c5f84f35a664803fcab2f7781')
+ commit = Commit(self.rorepo, id='33ebe7acec14b25c5f84f35a664803fcab2f7781')
stats = commit.stats
def check_entries(d):
@@ -48,13 +46,13 @@ class TestCommit(object):
git.return_value = fixture('rev_list_bisect_all')
- revs = self.repo.git.rev_list('HEAD',
+ revs = self.rorepo.git.rev_list('HEAD',
pretty='raw',
first_parent=True,
bisect_all=True)
assert_true(git.called)
- commits = Commit._iter_from_process_or_stream(self.repo, ListProcessAdapter(revs))
+ commits = Commit._iter_from_process_or_stream(self.rorepo, ListProcessAdapter(revs))
expected_ids = (
'cf37099ea8d1d8c7fbf9b6d12d7ec0249d3acb8b',
'33ebe7acec14b25c5f84f35a664803fcab2f7781',
@@ -66,29 +64,29 @@ class TestCommit(object):
assert_equal(sha1, commit.id)
def test_count(self):
- assert self.repo.tag('0.1.5').commit.count( ) == 141
+ assert self.rorepo.tag('0.1.5').commit.count( ) == 141
def test_list(self):
- assert isinstance(Commit.list_items(self.repo, '0.1.5', max_count=5)['5117c9c8a4d3af19a9958677e45cda9269de1541'], Commit)
+ assert isinstance(Commit.list_items(self.rorepo, '0.1.5', max_count=5)['5117c9c8a4d3af19a9958677e45cda9269de1541'], Commit)
def test_str(self):
- commit = Commit(self.repo, id='abc')
+ commit = Commit(self.rorepo, id='abc')
assert_equal ("abc", str(commit))
def test_repr(self):
- commit = Commit(self.repo, id='abc')
+ commit = Commit(self.rorepo, id='abc')
assert_equal('<git.Commit "abc">', repr(commit))
def test_equality(self):
- commit1 = Commit(self.repo, id='abc')
- commit2 = Commit(self.repo, id='abc')
- commit3 = Commit(self.repo, id='zyx')
+ commit1 = Commit(self.rorepo, id='abc')
+ commit2 = Commit(self.rorepo, id='abc')
+ commit3 = Commit(self.rorepo, id='zyx')
assert_equal(commit1, commit2)
assert_not_equal(commit2, commit3)
def test_iter_parents(self):
# should return all but ourselves, even if skip is defined
- c = self.repo.commit('0.1.5')
+ c = self.rorepo.commit('0.1.5')
for skip in (0, 1):
piter = c.iter_parents(skip=skip)
first_parent = piter.next()
diff --git a/test/git/test_config.py b/test/git/test_config.py
index 843da723..c2909b8f 100644
--- a/test/git/test_config.py
+++ b/test/git/test_config.py
@@ -11,10 +11,6 @@ from copy import copy
class TestBase(TestCase):
- @classmethod
- def setUpAll(cls):
- cls.repo = Repo(GIT_REPO)
-
def _to_memcache(self, file_path):
fp = open(file_path, "r")
sio = StringIO.StringIO()
diff --git a/test/git/test_diff.py b/test/git/test_diff.py
index 501d937d..d7505987 100644
--- a/test/git/test_diff.py
+++ b/test/git/test_diff.py
@@ -7,19 +7,17 @@
from test.testlib import *
from git import *
-class TestDiff(TestCase):
- def setUp(self):
- self.repo = Repo(GIT_REPO)
-
+class TestDiff(TestBase):
+
def test_list_from_string_new_mode(self):
output = ListProcessAdapter(fixture('diff_new_mode'))
- diffs = Diff._index_from_patch_format(self.repo, output.stdout)
+ diffs = Diff._index_from_patch_format(self.rorepo, output.stdout)
assert_equal(1, len(diffs))
assert_equal(10, len(diffs[0].diff.splitlines()))
def test_diff_with_rename(self):
output = ListProcessAdapter(fixture('diff_rename'))
- diffs = Diff._index_from_patch_format(self.repo, output.stdout)
+ diffs = Diff._index_from_patch_format(self.rorepo, output.stdout)
assert_equal(1, len(diffs))
@@ -37,13 +35,13 @@ class TestDiff(TestCase):
for fixture_name in fixtures:
diff_proc = ListProcessAdapter(fixture(fixture_name))
- diffs = Diff._index_from_patch_format(self.repo, diff_proc.stdout)
+ diffs = Diff._index_from_patch_format(self.rorepo, diff_proc.stdout)
# END for each fixture
def test_diff_interface(self):
# test a few variations of the main diff routine
assertion_map = dict()
- for i, commit in enumerate(self.repo.iter_commits('0.1.6', max_count=10)):
+ for i, commit in enumerate(self.rorepo.iter_commits('0.1.6', max_count=10)):
diff_item = commit
if i%2 == 0:
diff_item = commit.tree
diff --git a/test/git/test_git.py b/test/git/test_git.py
index 1f44aebc..c4a39e85 100644
--- a/test/git/test_git.py
+++ b/test/git/test_git.py
@@ -8,9 +8,11 @@ import os, sys
from test.testlib import *
from git import Git, GitCommandError
-class TestGit(object):
- def setup(self):
- self.git = Git(GIT_REPO)
+class TestGit(TestCase):
+
+ @classmethod
+ def setUpAll(cls):
+ cls.git = Git(GIT_REPO)
@patch_object(Git, 'execute')
def test_call_process_calls_execute(self, git):
diff --git a/test/git/test_head.py b/test/git/test_head.py
index b8380838..9b18ad7c 100644
--- a/test/git/test_head.py
+++ b/test/git/test_head.py
@@ -7,12 +7,10 @@
from test.testlib import *
from git import *
-class TestHead(object):
- def setup(self):
- self.repo = Repo(GIT_REPO)
+class TestHead(TestBase):
def test_base(self):
- for head in self.repo.heads:
+ for head in self.rorepo.heads:
assert head.name
assert "refs/heads" in head.path
# END for each head
@@ -20,7 +18,7 @@ class TestHead(object):
@patch_object(Git, '_call_process')
def test_ref_with_path_component(self, git):
git.return_value = fixture('for_each_ref_with_path_component')
- head = self.repo.heads[0]
+ head = self.rorepo.heads[0]
assert_equal('refactoring/feature1', head.name)
assert_true(git.called)
diff --git a/test/git/test_index.py b/test/git/test_index.py
index 4c17f5e5..10ffb79d 100644
--- a/test/git/test_index.py
+++ b/test/git/test_index.py
@@ -10,15 +10,11 @@ import inspect
import os
import tempfile
-class TestTree(TestCase):
+class TestTree(TestBase):
- @classmethod
- def setUpAll(cls):
- cls.repo = Repo(GIT_REPO)
-
def test_base(self):
# read from file
- index = Index.from_file(self.repo, fixture_path("index"))
+ index = Index.from_file(self.rorepo, fixture_path("index"))
assert index.entries
assert index.version > 0
@@ -31,7 +27,7 @@ class TestTree(TestCase):
# END for each method
# test stage
- index_merge = Index.from_file(self.repo, fixture_path("index_merge"))
+ index_merge = Index.from_file(self.rorepo, fixture_path("index_merge"))
assert len(index_merge.entries) == 106
assert len(list(e for e in index_merge.entries.itervalues() if e.stage != 0 ))
@@ -50,7 +46,7 @@ class TestTree(TestCase):
def _cmp_tree_index(self, tree, index):
# fail unless both objects contain the same paths and blobs
if isinstance(tree, str):
- tree = self.repo.commit(tree).tree
+ tree = self.rorepo.commit(tree).tree
num_blobs = 0
for blob in tree.traverse(predicate = lambda e: e.type == "blob"):
@@ -65,17 +61,17 @@ class TestTree(TestCase):
other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9"
# simple index from tree
- base_index = Index.from_tree(self.repo, common_ancestor_sha)
+ base_index = Index.from_tree(self.rorepo, common_ancestor_sha)
assert base_index.entries
self._cmp_tree_index(common_ancestor_sha, base_index)
# merge two trees - its like a fast-forward
- two_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha)
+ two_way_index = Index.from_tree(self.rorepo, common_ancestor_sha, cur_sha)
assert two_way_index.entries
self._cmp_tree_index(cur_sha, two_way_index)
# merge three trees - here we have a merge conflict
- three_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha)
+ three_way_index = Index.from_tree(self.rorepo, common_ancestor_sha, cur_sha, other_sha)
assert len(list(e for e in three_way_index.entries.values() if e.stage != 0))
diff --git a/test/git/test_performance.py b/test/git/test_performance.py
index 77567515..83d4a91e 100644
--- a/test/git/test_performance.py
+++ b/test/git/test_performance.py
@@ -8,9 +8,7 @@ from test.testlib import *
from git import *
from time import time
-class TestPerformance(object):
- def setup(self):
- self.repo = Repo(GIT_REPO)
+class TestPerformance(TestBase):
def test_iteration(self):
num_objs = 0
@@ -21,7 +19,7 @@ class TestPerformance(object):
# return quite a lot of commits, we just take one and hence abort the operation
st = time()
- for c in self.repo.iter_commits('0.1.6'):
+ for c in self.rorepo.iter_commits('0.1.6'):
num_commits += 1
c.author
c.authored_date
diff --git a/test/git/test_remote.py b/test/git/test_remote.py
index aeb6b4af..ef00056d 100644
--- a/test/git/test_remote.py
+++ b/test/git/test_remote.py
@@ -7,16 +7,13 @@
from test.testlib import *
from git import *
-class TestRemote(TestCase):
+class TestRemote(TestBase):
- @classmethod
- def setUpAll(cls):
- cls.repo = Repo(GIT_REPO)
-
- def test_base(self):
+ @with_rw_and_rw_remote_repo('0.1.6')
+ def test_base(self, rw_repo, remote_repo):
num_remotes = 0
remote_set = set()
- for remote in self.repo.remotes:
+ for remote in rw_repo.remotes:
num_remotes += 1
assert remote == remote
assert str(remote) != repr(remote)
@@ -64,27 +61,29 @@ class TestRemote(TestCase):
remote.fetch()
self.failUnlessRaises(GitCommandError, remote.pull)
+ remote.pull('master')
remote.update()
self.fail("test push once there is a test-repo")
# END for each remote
assert num_remotes
assert num_remotes == len(remote_set)
- origin = self.repo.remote('origin')
- assert origin == self.repo.remotes.origin
+ origin = rw_repo.remote('origin')
+ assert origin == rw_repo.remotes.origin
- def test_creation_and_removal(self):
+ @with_bare_rw_repo
+ def test_creation_and_removal(self, bare_rw_repo):
new_name = "test_new_one"
arg_list = (new_name, "git@server:hello.git")
- remote = Remote.create(self.repo, *arg_list )
+ remote = Remote.create(bare_rw_repo, *arg_list )
assert remote.name == "test_new_one"
# create same one again
- self.failUnlessRaises(GitCommandError, Remote.create, self.repo, *arg_list)
+ self.failUnlessRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list)
- Remote.remove(self.repo, new_name)
+ Remote.remove(bare_rw_repo, new_name)
- for remote in self.repo.remotes:
+ for remote in bare_rw_repo.remotes:
if remote.name == new_name:
raise AssertionError("Remote removal failed")
# END if deleted remote matches existing remote's name
diff --git a/test/git/test_repo.py b/test/git/test_repo.py
index ff10f6a6..02eea7de 100644
--- a/test/git/test_repo.py
+++ b/test/git/test_repo.py
@@ -8,11 +8,7 @@ import os, sys
from test.testlib import *
from git import *
-class TestRepo(TestCase):
-
- @classmethod
- def setUpAll(cls):
- cls.repo = Repo(GIT_REPO)
+class TestRepo(TestBase):
@raises(InvalidGitRepositoryError)
def test_new_should_raise_on_invalid_repo_location(self):
@@ -27,27 +23,27 @@ class TestRepo(TestCase):
def test_description(self):
txt = "Test repository"
- self.repo.description = txt
- assert_equal(self.repo.description, txt)
+ self.rorepo.description = txt
+ assert_equal(self.rorepo.description, txt)
def test_heads_should_return_array_of_head_objects(self):
- for head in self.repo.heads:
+ for head in self.rorepo.heads:
assert_equal(Head, head.__class__)
def test_heads_should_populate_head_data(self):
- for head in self.repo.heads:
+ for head in self.rorepo.heads:
assert head.name
assert isinstance(head.commit,Commit)
# END for each head
- assert isinstance(self.repo.heads.master, Head)
- assert isinstance(self.repo.heads['master'], Head)
+ assert isinstance(self.rorepo.heads.master, Head)
+ assert isinstance(self.rorepo.heads['master'], Head)
@patch_object(Git, '_call_process')
def test_commits(self, git):
git.return_value = ListProcessAdapter(fixture('rev_list'))
- commits = list( self.repo.iter_commits('master', max_count=10) )
+ commits = list( self.rorepo.iter_commits('master', max_count=10) )
c = commits[0]
assert_equal('4c8124ffcf4039d292442eeccabdeca5af5c5017', c.id)
@@ -73,7 +69,7 @@ class TestRepo(TestCase):
def test_trees(self):
mc = 30
num_trees = 0
- for tree in self.repo.iter_trees('0.1.5', max_count=mc):
+ for tree in self.rorepo.iter_trees('0.1.5', max_count=mc):
num_trees += 1
assert isinstance(tree, Tree)
# END for each tree
@@ -93,7 +89,7 @@ class TestRepo(TestCase):
assert_true(repo.called)
def test_bare_property(self):
- self.repo.bare
+ self.rorepo.bare
@patch_object(Repo, '__init__')
@patch_object(Git, '_call_process')
@@ -113,7 +109,7 @@ class TestRepo(TestCase):
git.return_value = None
repo.return_value = None
- self.repo.clone("repos/foo/bar.git")
+ self.rorepo.clone("repos/foo/bar.git")
assert_true(git.called)
path = os.path.join(absolute_project_path(), '.git')
@@ -126,7 +122,7 @@ class TestRepo(TestCase):
git.return_value = None
repo.return_value = None
- self.repo.clone("repos/foo/bar.git", **{'template': '/awesome'})
+ self.rorepo.clone("repos/foo/bar.git", **{'template': '/awesome'})
assert_true(git.called)
path = os.path.join(absolute_project_path(), '.git')
@@ -136,63 +132,63 @@ class TestRepo(TestCase):
def test_daemon_export(self):
- orig_val = self.repo.daemon_export
- self.repo.daemon_export = not orig_val
- assert self.repo.daemon_export == ( not orig_val )
- self.repo.daemon_export = orig_val
- assert self.repo.daemon_export == orig_val
+ orig_val = self.rorepo.daemon_export
+ self.rorepo.daemon_export = not orig_val
+ assert self.rorepo.daemon_export == ( not orig_val )
+ self.rorepo.daemon_export = orig_val
+ assert self.rorepo.daemon_export == orig_val
def test_alternates(self):
- cur_alternates = self.repo.alternates
+ cur_alternates = self.rorepo.alternates
# empty alternates
- self.repo.alternates = []
- assert self.repo.alternates == []
+ self.rorepo.alternates = []
+ assert self.rorepo.alternates == []
alts = [ "other/location", "this/location" ]
- self.repo.alternates = alts
- assert alts == self.repo.alternates
- self.repo.alternates = cur_alternates
+ self.rorepo.alternates = alts
+ assert alts == self.rorepo.alternates
+ self.rorepo.alternates = cur_alternates
def test_repr(self):
path = os.path.join(os.path.abspath(GIT_REPO), '.git')
- assert_equal('<git.Repo "%s">' % path, repr(self.repo))
+ assert_equal('<git.Repo "%s">' % path, repr(self.rorepo))
def test_is_dirty_with_bare_repository(self):
- self.repo._bare = True
- assert_false(self.repo.is_dirty)
+ self.rorepo._bare = True
+ assert_false(self.rorepo.is_dirty)
def test_is_dirty(self):
- self.repo._bare = False
+ self.rorepo._bare = False
for index in (0,1):
for working_tree in (0,1):
for untracked_files in (0,1):
- assert self.repo.is_dirty in (True, False)
+ assert self.rorepo.is_dirty in (True, False)
# END untracked files
# END working tree
# END index
- self.repo._bare = True
- assert self.repo.is_dirty == False
+ self.rorepo._bare = True
+ assert self.rorepo.is_dirty == False
@patch_object(Git, '_call_process')
def test_active_branch(self, git):
git.return_value = 'refs/heads/major-refactoring'
- assert_equal(self.repo.active_branch.name, 'major-refactoring')
+ assert_equal(self.rorepo.active_branch.name, 'major-refactoring')
assert_equal(git.call_args, (('symbolic_ref', 'HEAD'), {}))
def test_head(self):
- assert self.repo.head.object == self.repo.active_branch.object
+ assert self.rorepo.head.object == self.rorepo.active_branch.object
def test_tag(self):
- assert self.repo.tag('0.1.5').commit
+ assert self.rorepo.tag('0.1.5').commit
def test_archive(self):
tmpfile = os.tmpfile()
- self.repo.archive(tmpfile, '0.1.5')
+ self.rorepo.archive(tmpfile, '0.1.5')
assert tmpfile.tell()
@patch_object(Git, '_call_process')
def test_should_display_blame_information(self, git):
git.return_value = fixture('blame')
- b = self.repo.blame( 'master', 'lib/git.py')
+ b = self.rorepo.blame( 'master', 'lib/git.py')
assert_equal(13, len(b))
assert_equal( 2, len(b[0]) )
# assert_equal(25, reduce(lambda acc, x: acc + len(x[-1]), b))
@@ -217,7 +213,7 @@ class TestRepo(TestCase):
assert_true( len( tlist ) < sum( len(t) for t in tlist ) ) # test for single-char bug
def test_untracked_files(self):
- base = self.repo.git.git_dir
+ base = self.rorepo.git.git_dir
files = (base+"/__test_myfile", base+"/__test_other_file")
num_recently_untracked = 0
try:
@@ -225,7 +221,7 @@ class TestRepo(TestCase):
fd = open(fpath,"wb")
fd.close()
# END for each filename
- untracked_files = self.repo.untracked_files
+ untracked_files = self.rorepo.untracked_files
num_recently_untracked = len(untracked_files)
# assure we have all names - they are relative to the git-dir
@@ -239,18 +235,18 @@ class TestRepo(TestCase):
os.remove(fpath)
# END handle files
- assert len(self.repo.untracked_files) == (num_recently_untracked - len(files))
+ assert len(self.rorepo.untracked_files) == (num_recently_untracked - len(files))
def test_config_reader(self):
- reader = self.repo.config_reader() # all config files
+ reader = self.rorepo.config_reader() # all config files
assert reader.read_only
- reader = self.repo.config_reader("repository") # single config file
+ reader = self.rorepo.config_reader("repository") # single config file
assert reader.read_only
def test_config_writer(self):
- for config_level in self.repo.config_level:
+ for config_level in self.rorepo.config_level:
try:
- writer = self.repo.config_writer(config_level)
+ writer = self.rorepo.config_writer(config_level)
assert not writer.read_only
except IOError:
# its okay not to get a writer for some configuration files if we
diff --git a/test/git/test_stats.py b/test/git/test_stats.py
index 706f29a4..7392a96e 100644
--- a/test/git/test_stats.py
+++ b/test/git/test_stats.py
@@ -7,13 +7,11 @@
from test.testlib import *
from git import *
-class TestStats(object):
- def setup(self):
- self.repo = Repo(GIT_REPO)
+class TestStats(TestBase):
def test__list_from_string(self):
output = fixture('diff_numstat')
- stats = Stats._list_from_string(self.repo, output)
+ stats = Stats._list_from_string(self.rorepo, output)
assert_equal(2, stats.total['files'])
assert_equal(52, stats.total['lines'])
diff --git a/test/git/test_tag.py b/test/git/test_tag.py
index 9641e0ac..97e0acd1 100644
--- a/test/git/test_tag.py
+++ b/test/git/test_tag.py
@@ -9,13 +9,11 @@ from test.testlib import *
from git import *
from git.objects.tag import TagObject
-class TestTag(object):
- def setup(self):
- self.repo = Repo(GIT_REPO)
+class TestTag(TestBase):
def test_tag_base(self):
tag_object_refs = list()
- for tag in self.repo.tags:
+ for tag in self.rorepo.tags:
assert "refs/tags" in tag.path
assert tag.name
assert isinstance( tag.commit, Commit )
@@ -30,6 +28,6 @@ class TestTag(object):
# END if we have a tag object
# END for tag in repo-tags
assert tag_object_refs
- assert isinstance(self.repo.tags['0.1.5'], TagReference)
+ assert isinstance(self.rorepo.tags['0.1.5'], TagReference)
diff --git a/test/testlib/__init__.py b/test/testlib/__init__.py
index f364171b..2133eb8c 100644
--- a/test/testlib/__init__.py
+++ b/test/testlib/__init__.py
@@ -8,7 +8,6 @@ import inspect
from mock import *
from asserts import *
from helper import *
-from unittest import TestCase
__all__ = [ name for name, obj in locals().items()
if not (name.startswith('_') or inspect.ismodule(obj)) ]
diff --git a/test/testlib/helper.py b/test/testlib/helper.py
index b34c9303..eef7876f 100644
--- a/test/testlib/helper.py
+++ b/test/testlib/helper.py
@@ -5,6 +5,10 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os
+from git import Repo
+from unittest import TestCase
+import tempfile
+import shutil
GIT_REPO = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
@@ -58,3 +62,117 @@ class ListProcessAdapter(object):
return 0
poll = wait
+
+
+def with_bare_rw_repo(func):
+ """
+ Decorator providing a specially made read-write repository to the test case
+ decorated with it. The test case requires the following signature::
+ def case(self, rw_repo)
+
+ The rwrepo will be a bare clone or the types rorepo. Once the method finishes,
+ it will be removed completely.
+
+ Use this if you want to make purely index based adjustments, change refs, create
+ heads, generally operations that do not need a working tree.
+ """
+ def bare_repo_creator(self):
+ repo_dir = tempfile.mktemp("bare_repo")
+ rw_repo = self.rorepo.clone(repo_dir, shared=True, bare=True)
+ try:
+ return func(self, rw_repo)
+ finally:
+ shutil.rmtree(repo_dir)
+ # END cleanup
+ # END bare repo creator
+ bare_repo_creator.__name__ = func.__name__
+ return bare_repo_creator
+
+def with_rw_repo(working_tree_ref):
+ """
+ Same as with_bare_repo, but clones the rorepo as non-bare repository, checking
+ out the working tree at the given working_tree_ref.
+
+ This repository type is more costly due to the working copy checkout.
+ """
+ assert isinstance(working_tree_ref, basestring), "Decorator requires ref name for working tree checkout"
+ def argument_passer(func):
+ def repo_creator(self):
+ repo_dir = tempfile.mktemp("non_bare_repo")
+ rw_repo = self.rorepo.clone(repo_dir, shared=True, bare=False, n=True)
+ rw_repo.git.checkout(working_tree_ref)
+ try:
+ return func(self, rw_repo)
+ finally:
+ shutil.rmtree(repo_dir)
+ # END cleanup
+ # END rw repo creator
+ repo_creator.__name__ = func.__name__
+ return repo_creator
+ # END argument passer
+ return argument_passer
+
+def with_rw_and_rw_remote_repo(working_tree_ref):
+ """
+ Same as with_rw_repo, but also provides a writable remote repository from which the
+ rw_repo has been forked. The remote repository was cloned as bare repository from
+ the rorepo, wheras the rw repo has a working tree and was cloned from the remote repository.
+
+ The following scetch demonstrates this::
+ rorepo ---<bare clone>---> rw_remote_repo ---<clone>---> rw_repo
+
+ The test case needs to support the following signature::
+ def case(self, rw_repo, rw_remote_repo)
+
+ This setup allows you to test push and pull scenarios and hooks nicely.
+ """
+ assert isinstance(working_tree_ref, basestring), "Decorator requires ref name for working tree checkout"
+ def argument_passer(func):
+ def remote_repo_creator(self):
+ remote_repo_dir = tempfile.mktemp("remote_repo")
+ repo_dir = tempfile.mktemp("remote_clone_non_bare_repo")
+
+ rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True)
+ rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) # recursive alternates info ?
+ rw_repo.git.checkout(working_tree_ref)
+ try:
+ return func(self, rw_repo, rw_remote_repo)
+ finally:
+ shutil.rmtree(repo_dir)
+ shutil.rmtree(remote_repo_dir)
+ # END cleanup
+ # END bare repo creator
+ remote_repo_creator.__name__ = func.__name__
+ return remote_repo_creator
+ # END remote repo creator
+ # END argument parsser
+
+ return argument_passer
+
+
+class TestBase(TestCase):
+ """
+ Base Class providing default functionality to all tests such as:
+
+ - Utility functions provided by the TestCase base of the unittest method such as::
+ self.fail("todo")
+ self.failUnlessRaises(...)
+
+ - Class level repository which is considered read-only as it is shared among
+ all test cases in your type.
+ Access it using::
+ self.rorepo # 'ro' stands for read-only
+
+ The rorepo is in fact your current project's git repo. If you refer to specific
+ shas for your objects, be sure you choose some that are part of the immutable portion
+ of the project history ( to assure tests don't fail for others ).
+ """
+
+ @classmethod
+ def setUpAll(cls):
+ """
+ Dynamically add a read-only repository to our actual type. This way
+ each test type has its own repository
+ """
+ cls.rorepo = Repo(GIT_REPO)
+