| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -138,6 +138,12 @@ Remote | |||
| 138 | 138 | * Repo.remotes lists all remotes | |
| 139 | 139 | * Repo.remote returns a remote of the specified name if it exists | |
| 140 | 140 | ||
| 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 | + | ||
| 141 | 147 | Tree | |
| 142 | 148 | ---- | |
| 143 | 149 | * former 'name' member renamed to path as it suits the actual data better | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,16 +14,13 @@ | |||
| 14 | 14 | from git.objects.utils import get_object_type_by_name | |
| 15 | 15 | import tempfile | |
| 16 | 16 | ||
| 17 | - class TestBase(object): | ||
| 17 | + class TestBase(TestBase): | ||
| 18 | 18 | ||
| 19 | 19 | type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070"), | |
| 20 | 20 | ("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79"), | |
| 21 | 21 | ("commit", "4251bd59fb8e11e40c40548cba38180a9536118c"), | |
| 22 | 22 | ("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10") ) | |
| 23 | 23 | ||
| 24 | - def setup(self): | ||
| 25 | - self.repo = Repo(GIT_REPO) | ||
| 26 | - | ||
| 27 | 24 | def test_base_object(self): | |
| 28 | 25 | # test interface of base object classes | |
| 29 | 26 | types = (Blob, Tree, Commit, TagObject) | |
@@ -33,7 +30,7 @@ def test_base_object(self): | |||
| 33 | 30 | num_objs = 0 | |
| 34 | 31 | num_index_objs = 0 | |
| 35 | 32 | 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) | ||
| 37 | 34 | num_objs += 1 | |
| 38 | 35 | assert item.id == hexsha | |
| 39 | 36 | assert item.type == typename | |
@@ -74,7 +71,7 @@ def test_tags(self): | |||
| 74 | 71 | # tag refs can point to tag objects or to commits | |
| 75 | 72 | s = set() | |
| 76 | 73 | 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): | ||
| 78 | 75 | ref_count += 1 | |
| 79 | 76 | assert isinstance(ref, refs.Reference) | |
| 80 | 77 | assert str(ref) == ref.name | |
@@ -88,7 +85,7 @@ def test_tags(self): | |||
| 88 | 85 | ||
| 89 | 86 | def test_heads(self): | |
| 90 | 87 | # see how it dynmically updates its object | |
| 91 | - for head in self.repo.heads: | ||
| 88 | + for head in self.rorepo.heads: | ||
| 92 | 89 | head.name | |
| 93 | 90 | head.path | |
| 94 | 91 | prev_object = head.object | |
@@ -106,4 +103,17 @@ def test_get_object_type_by_name(self): | |||
| 106 | 103 | ||
| 107 | 104 | def test_object_resolution(self): | |
| 108 | 105 | # 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") | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,6 @@ | |||
| 8 | 8 | from mock import * | |
| 9 | 9 | from asserts import * | |
| 10 | 10 | from helper import * | |
| 11 | - from unittest import TestCase | ||
| 12 | 11 | ||
| 13 | 12 | __all__ = [ name for name, obj in locals().items() | |
| 14 | 13 | if not (name.startswith('_') or inspect.ismodule(obj)) ] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,8 @@ | |||
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | ||
| 7 | 7 | import os | |
| 8 | + from git import Repo | ||
| 9 | + from unittest import TestCase | ||
| 8 | 10 | ||
| 9 | 11 | GIT_REPO = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) | |
| 10 | 12 | ||
@@ -58,3 +60,99 @@ def wait(self): | |||
| 58 | 60 | return 0 | |
| 59 | 61 | ||
| 60 | 62 | 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 | + | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments