X Tutup
Skip to content

Commit bb0ac30

Browse files
committed
Added frame for new Repo handling and some neat decorators, including tests that test whether the testing framework does what it should
1 parent 59e2643 commit bb0ac30

File tree

4 files changed

+122
-9
lines changed

4 files changed

+122
-9
lines changed

CHANGES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ Remote
138138
* Repo.remotes lists all remotes
139139
* Repo.remote returns a remote of the specified name if it exists
140140

141+
Test Framework
142+
--------------
143+
* Added support for common TestCase base class that provides additional functionality
144+
to receive repositories tests can also write to. This way, more aspects can be
145+
tested under real-world ( un-mocked ) conditions.
146+
141147
Tree
142148
----
143149
* former 'name' member renamed to path as it suits the actual data better

test/git/test_base.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,13 @@
1414
from git.objects.utils import get_object_type_by_name
1515
import tempfile
1616

17-
class TestBase(object):
17+
class TestBase(TestBase):
1818

1919
type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070"),
2020
("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79"),
2121
("commit", "4251bd59fb8e11e40c40548cba38180a9536118c"),
2222
("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10") )
2323

24-
def setup(self):
25-
self.repo = Repo(GIT_REPO)
26-
2724
def test_base_object(self):
2825
# test interface of base object classes
2926
types = (Blob, Tree, Commit, TagObject)
@@ -33,7 +30,7 @@ def test_base_object(self):
3330
num_objs = 0
3431
num_index_objs = 0
3532
for obj_type, (typename, hexsha) in zip(types, self.type_tuples):
36-
item = obj_type(self.repo,hexsha)
33+
item = obj_type(self.rorepo,hexsha)
3734
num_objs += 1
3835
assert item.id == hexsha
3936
assert item.type == typename
@@ -74,7 +71,7 @@ def test_tags(self):
7471
# tag refs can point to tag objects or to commits
7572
s = set()
7673
ref_count = 0
77-
for ref in chain(self.repo.tags, self.repo.heads):
74+
for ref in chain(self.rorepo.tags, self.rorepo.heads):
7875
ref_count += 1
7976
assert isinstance(ref, refs.Reference)
8077
assert str(ref) == ref.name
@@ -88,7 +85,7 @@ def test_tags(self):
8885

8986
def test_heads(self):
9087
# see how it dynmically updates its object
91-
for head in self.repo.heads:
88+
for head in self.rorepo.heads:
9289
head.name
9390
head.path
9491
prev_object = head.object
@@ -106,4 +103,17 @@ def test_get_object_type_by_name(self):
106103

107104
def test_object_resolution(self):
108105
# objects must be resolved to shas so they compare equal
109-
assert self.repo.head.object == self.repo.active_branch.object
106+
assert self.rorepo.head.object == self.rorepo.active_branch.object
107+
108+
@with_bare_rw_repo
109+
def test_with_bare_rw_repo(self, bare_rw_repo):
110+
assert bare_rw_repo.config_reader("repository").getboolean("core", "bare")
111+
112+
@with_rw_repo
113+
def test_with_rw_repo(self, rw_repo):
114+
assert not rw_repo.config_reader("repository").getboolean("core", "bare")
115+
116+
@with_rw_and_rw_remote_repo
117+
def test_with_rw_remote_and_rw_repo(self, rw_repo, rw_remote_repo):
118+
assert not rw_repo.config_reader("repository").getboolean("core", "bare")
119+
assert rw_remote_repo.config_reader("repository").getboolean("core", "bare")

test/testlib/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from mock import *
99
from asserts import *
1010
from helper import *
11-
from unittest import TestCase
1211

1312
__all__ = [ name for name, obj in locals().items()
1413
if not (name.startswith('_') or inspect.ismodule(obj)) ]

test/testlib/helper.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
import os
8+
from git import Repo
9+
from unittest import TestCase
810

911
GIT_REPO = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
1012

@@ -58,3 +60,99 @@ def wait(self):
5860
return 0
5961

6062
poll = wait
63+
64+
65+
def with_bare_rw_repo(func):
66+
"""
67+
Decorator providing a specially made read-write repository to the test case
68+
decorated with it. The test case requires the following signature::
69+
def case(self, rw_repo)
70+
71+
The rwrepo will be a bare clone or the types rorepo. Once the method finishes,
72+
it will be removed completely.
73+
74+
Use this if you want to make purely index based adjustments, change refs, create
75+
heads, generally operations that do not need a working tree.
76+
"""
77+
def bare_repo_creator(self):
78+
rw_repo = None
79+
try:
80+
return func(self, rw_repo)
81+
finally:
82+
pass
83+
# END cleanup
84+
# END bare repo creator
85+
bare_repo_creator.__name__ = func.__name__
86+
return bare_repo_creator
87+
88+
def with_rw_repo(func, working_tree_ref='0.1.6'):
89+
"""
90+
Same as with_bare_repo, but clones the rorepo as non-bare repository, checking
91+
out the working tree at the given working_tree_ref.
92+
93+
This repository type is more costly due to the working copy checkout.
94+
"""
95+
def repo_creator(self):
96+
rw_repo = None
97+
try:
98+
return func(self, rw_repo)
99+
finally:
100+
pass
101+
# END cleanup
102+
# END bare repo creator
103+
repo_creator.__name__ = func.__name__
104+
return repo_creator
105+
106+
def with_rw_and_rw_remote_repo(func):
107+
"""
108+
Same as with_rw_repo, but also provides a writable remote repository from which the
109+
rw_repo has been forked. The remote repository was cloned as bare repository from
110+
the rorepo, wheras the rw repo has a working tree and was cloned from the remote repository.
111+
112+
The following scetch demonstrates this::
113+
rorepo ---<bare clone>---> rw_remote_repo ---<clone>---> rw_repo
114+
115+
The test case needs to support the following signature::
116+
def case(self, rw_repo, rw_remote_repo)
117+
118+
This setup allows you to test push and pull scenarios and hooks nicely.
119+
"""
120+
def remote_repo_creator(self):
121+
rw_repo = None
122+
rw_remote_repo = None
123+
try:
124+
return func(self, rw_repo, rw_remote_repo)
125+
finally:
126+
pass
127+
# END cleanup
128+
# END bare repo creator
129+
remote_repo_creator.__name__ = func.__name__
130+
return remote_repo_creator
131+
132+
133+
class TestBase(TestCase):
134+
"""
135+
Base Class providing default functionality to all tests such as:
136+
137+
- Utility functions provided by the TestCase base of the unittest method such as::
138+
self.fail("todo")
139+
self.failUnlessRaises(...)
140+
141+
- Class level repository which is considered read-only as it is shared among
142+
all test cases in your type.
143+
Access it using::
144+
self.rorepo # 'ro' stands for read-only
145+
146+
The rorepo is in fact your current project's git repo. If you refer to specific
147+
shas for your objects, be sure you choose some that are part of the immutable portion
148+
of the project history ( to assure tests don't fail for others ).
149+
"""
150+
151+
@classmethod
152+
def setUpAll(cls):
153+
"""
154+
Dynamically add a read-only repository to our actual type. This way
155+
each test type has its own repository
156+
"""
157+
cls.rorepo = Repo(GIT_REPO)
158+

0 commit comments

Comments
 (0)
X Tutup