Skip to content

Commit 14e0f65

Browse files
nejchJohnVillalovos
authored andcommitted
test(unit): split the last remaining unittest-based classes into modules"
1 parent 4a9e3ee commit 14e0f65

File tree

5 files changed

+417
-388
lines changed

5 files changed

+417
-388
lines changed

tests/unit/base/test_rest_manager.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from gitlab import base
2+
from tests.unit import helpers
3+
4+
5+
def test_computed_path_simple(gl):
6+
class MGR(base.RESTManager):
7+
_path = "/tests"
8+
_obj_cls = object
9+
10+
mgr = MGR(gl)
11+
assert mgr._computed_path == "/tests"
12+
13+
14+
def test_computed_path_with_parent(gl, fake_manager):
15+
class MGR(base.RESTManager):
16+
_path = "/tests/{test_id}/cases"
17+
_obj_cls = object
18+
_from_parent_attrs = {"test_id": "id"}
19+
20+
mgr = MGR(gl, parent=helpers.FakeParent(manager=fake_manager, attrs={}))
21+
assert mgr._computed_path == "/tests/42/cases"
22+
23+
24+
def test_path_property(gl):
25+
class MGR(base.RESTManager):
26+
_path = "/tests"
27+
_obj_cls = object
28+
29+
mgr = MGR(gl)
30+
assert mgr.path == "/tests"

tests/unit/base/test_rest_object.py

+337
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
import pickle
2+
3+
import pytest
4+
5+
import gitlab
6+
from gitlab import base
7+
from tests.unit import helpers
8+
from tests.unit.helpers import FakeManager # noqa: F401, needed for _create_managers
9+
10+
11+
def test_instantiate(gl, fake_manager):
12+
attrs = {"foo": "bar"}
13+
obj = helpers.FakeObject(fake_manager, attrs.copy())
14+
15+
assert attrs == obj._attrs
16+
assert {} == obj._updated_attrs
17+
assert obj._create_managers() is None
18+
assert fake_manager == obj.manager
19+
assert gl == obj.manager.gitlab
20+
assert str(obj) == f"{type(obj)} => {attrs}"
21+
22+
23+
def test_instantiate_non_dict(gl, fake_manager):
24+
with pytest.raises(gitlab.exceptions.GitlabParsingError):
25+
helpers.FakeObject(fake_manager, ["a", "list", "fails"])
26+
27+
28+
def test_missing_attribute_does_not_raise_custom(gl, fake_manager):
29+
"""Ensure a missing attribute does not raise our custom error message
30+
if the RESTObject was not created from a list"""
31+
obj = helpers.FakeObject(manager=fake_manager, attrs={"foo": "bar"})
32+
with pytest.raises(AttributeError) as excinfo:
33+
obj.missing_attribute
34+
exc_str = str(excinfo.value)
35+
assert "missing_attribute" in exc_str
36+
assert "was created via a list()" not in exc_str
37+
assert base._URL_ATTRIBUTE_ERROR not in exc_str
38+
39+
40+
def test_missing_attribute_from_list_raises_custom(gl, fake_manager):
41+
"""Ensure a missing attribute raises our custom error message if the
42+
RESTObject was created from a list"""
43+
obj = helpers.FakeObject(
44+
manager=fake_manager, attrs={"foo": "bar"}, created_from_list=True
45+
)
46+
with pytest.raises(AttributeError) as excinfo:
47+
obj.missing_attribute
48+
exc_str = str(excinfo.value)
49+
assert "missing_attribute" in exc_str
50+
assert "was created via a list()" in exc_str
51+
assert base._URL_ATTRIBUTE_ERROR in exc_str
52+
53+
54+
def test_picklability(fake_manager):
55+
obj = helpers.FakeObject(fake_manager, {"foo": "bar"})
56+
original_obj_module = obj._module
57+
pickled = pickle.dumps(obj)
58+
unpickled = pickle.loads(pickled)
59+
assert isinstance(unpickled, helpers.FakeObject)
60+
assert hasattr(unpickled, "_module")
61+
assert unpickled._module == original_obj_module
62+
pickle.dumps(unpickled)
63+
64+
65+
def test_attrs(fake_manager):
66+
obj = helpers.FakeObject(fake_manager, {"foo": "bar"})
67+
68+
assert "bar" == obj.foo
69+
with pytest.raises(AttributeError):
70+
getattr(obj, "bar")
71+
72+
obj.bar = "baz"
73+
assert "baz" == obj.bar
74+
assert {"foo": "bar"} == obj._attrs
75+
assert {"bar": "baz"} == obj._updated_attrs
76+
77+
78+
def test_get_id(fake_manager):
79+
obj = helpers.FakeObject(fake_manager, {"foo": "bar"})
80+
obj.id = 42
81+
assert 42 == obj.get_id()
82+
83+
obj.id = None
84+
assert obj.get_id() is None
85+
86+
87+
def test_encoded_id(fake_manager):
88+
obj = helpers.FakeObject(fake_manager, {"foo": "bar"})
89+
obj.id = 42
90+
assert 42 == obj.encoded_id
91+
92+
obj.id = None
93+
assert obj.encoded_id is None
94+
95+
obj.id = "plain"
96+
assert "plain" == obj.encoded_id
97+
98+
obj.id = "a/path"
99+
assert "a%2Fpath" == obj.encoded_id
100+
101+
# If you assign it again it does not double URL-encode
102+
obj.id = obj.encoded_id
103+
assert "a%2Fpath" == obj.encoded_id
104+
105+
106+
def test_custom_id_attr(fake_manager):
107+
obj = helpers.OtherFakeObject(fake_manager, {"foo": "bar"})
108+
assert "bar" == obj.get_id()
109+
110+
111+
def test_update_attrs(fake_manager):
112+
obj = helpers.FakeObject(fake_manager, {"foo": "bar"})
113+
obj.bar = "baz"
114+
obj._update_attrs({"foo": "foo", "bar": "bar"})
115+
assert {"foo": "foo", "bar": "bar"} == obj._attrs
116+
assert {} == obj._updated_attrs
117+
118+
119+
def test_update_attrs_deleted(fake_manager):
120+
obj = helpers.FakeObject(fake_manager, {"foo": "foo", "bar": "bar"})
121+
obj.bar = "baz"
122+
obj._update_attrs({"foo": "foo"})
123+
assert {"foo": "foo"} == obj._attrs
124+
assert {} == obj._updated_attrs
125+
126+
127+
def test_dir_unique(fake_manager):
128+
obj = helpers.FakeObject(fake_manager, {"manager": "foo"})
129+
assert len(dir(obj)) == len(set(dir(obj)))
130+
131+
132+
def test_create_managers(gl, fake_manager):
133+
class ObjectWithManager(helpers.FakeObject):
134+
fakes: "FakeManager"
135+
136+
obj = ObjectWithManager(fake_manager, {"foo": "bar"})
137+
obj.id = 42
138+
assert isinstance(obj.fakes, helpers.FakeManager)
139+
assert obj.fakes.gitlab == gl
140+
assert obj.fakes._parent == obj
141+
142+
143+
def test_equality(fake_manager):
144+
obj1 = helpers.FakeObject(fake_manager, {"id": "foo"})
145+
obj2 = helpers.FakeObject(fake_manager, {"id": "foo", "other_attr": "bar"})
146+
assert obj1 == obj2
147+
assert len(set((obj1, obj2))) == 1
148+
149+
150+
def test_equality_custom_id(fake_manager):
151+
obj1 = helpers.OtherFakeObject(fake_manager, {"foo": "bar"})
152+
obj2 = helpers.OtherFakeObject(fake_manager, {"foo": "bar", "other_attr": "baz"})
153+
assert obj1 == obj2
154+
155+
156+
def test_equality_no_id(fake_manager):
157+
obj1 = helpers.FakeObject(fake_manager, {"attr1": "foo"})
158+
obj2 = helpers.FakeObject(fake_manager, {"attr1": "bar"})
159+
assert not obj1 == obj2
160+
161+
162+
def test_inequality(fake_manager):
163+
obj1 = helpers.FakeObject(fake_manager, {"id": "foo"})
164+
obj2 = helpers.FakeObject(fake_manager, {"id": "bar"})
165+
assert obj1 != obj2
166+
167+
168+
def test_inequality_no_id(fake_manager):
169+
obj1 = helpers.FakeObject(fake_manager, {"attr1": "foo"})
170+
obj2 = helpers.FakeObject(fake_manager, {"attr1": "bar"})
171+
assert obj1 != obj2
172+
assert len(set((obj1, obj2))) == 2
173+
174+
175+
def test_equality_with_other_objects(fake_manager):
176+
obj1 = helpers.FakeObject(fake_manager, {"id": "foo"})
177+
obj2 = None
178+
assert not obj1 == obj2
179+
180+
181+
def test_dunder_str(fake_manager):
182+
fake_object = helpers.FakeObject(fake_manager, {"attr1": "foo"})
183+
assert str(fake_object) == (
184+
"<class 'tests.unit.helpers.FakeObject'> => {'attr1': 'foo'}"
185+
)
186+
187+
188+
@pytest.mark.parametrize(
189+
"id_attr,repr_attr, attrs, expected_repr",
190+
[
191+
("id", None, {"id": 1}, "<ReprObject id:1>"),
192+
(
193+
"id",
194+
"name",
195+
{"id": 1, "name": "fake"},
196+
"<ReprObject id:1 name:fake>",
197+
),
198+
("name", "name", {"name": "fake"}, "<ReprObject name:fake>"),
199+
("id", "name", {"id": 1}, "<ReprObject id:1>"),
200+
(None, None, {}, "<ReprObject>"),
201+
(None, "name", {"name": "fake"}, "<ReprObject name:fake>"),
202+
(None, "name", {}, "<ReprObject>"),
203+
],
204+
ids=[
205+
"GetMixin with id",
206+
"GetMixin with id and _repr_attr",
207+
"GetMixin with _repr_attr matching _id_attr",
208+
"GetMixin with _repr_attr without _repr_attr value defined",
209+
"GetWithoutIDMixin",
210+
"GetWithoutIDMixin with _repr_attr",
211+
"GetWithoutIDMixin with _repr_attr without _repr_attr value defined",
212+
],
213+
)
214+
def test_dunder_repr(fake_manager, id_attr, repr_attr, attrs, expected_repr):
215+
class ReprObject(helpers.FakeObject):
216+
_id_attr = id_attr
217+
_repr_attr = repr_attr
218+
219+
fake_object = ReprObject(fake_manager, attrs)
220+
221+
assert repr(fake_object) == expected_repr
222+
223+
224+
def test_pformat(fake_manager):
225+
fake_object = helpers.FakeObject(
226+
fake_manager, {"attr1": "foo" * 10, "ham": "eggs" * 15}
227+
)
228+
assert fake_object.pformat() == (
229+
"<class 'tests.unit.helpers.FakeObject'> => "
230+
"\n{'attr1': 'foofoofoofoofoofoofoofoofoofoo',\n"
231+
" 'ham': 'eggseggseggseggseggseggseggseggseggseggseggseggseggseggseggs'}"
232+
)
233+
234+
235+
def test_pprint(capfd, fake_manager):
236+
fake_object = helpers.FakeObject(
237+
fake_manager, {"attr1": "foo" * 10, "ham": "eggs" * 15}
238+
)
239+
result = fake_object.pprint()
240+
assert result is None
241+
stdout, stderr = capfd.readouterr()
242+
assert stdout == (
243+
"<class 'tests.unit.helpers.FakeObject'> => "
244+
"\n{'attr1': 'foofoofoofoofoofoofoofoofoofoo',\n"
245+
" 'ham': 'eggseggseggseggseggseggseggseggseggseggseggseggseggseggseggs'}\n"
246+
)
247+
assert stderr == ""
248+
249+
250+
def test_repr(fake_manager):
251+
attrs = {"attr1": "foo"}
252+
obj = helpers.FakeObject(fake_manager, attrs)
253+
assert repr(obj) == "<FakeObject id:None>"
254+
255+
helpers.FakeObject._id_attr = None
256+
assert repr(obj) == "<FakeObject>"
257+
258+
259+
def test_attributes_get(fake_object):
260+
assert fake_object.attr1 == "foo"
261+
result = fake_object.attributes
262+
assert result == {"attr1": "foo", "alist": [1, 2, 3]}
263+
264+
265+
def test_attributes_shows_updates(fake_object):
266+
# Updated attribute value is reflected in `attributes`
267+
fake_object.attr1 = "hello"
268+
assert fake_object.attributes == {"attr1": "hello", "alist": [1, 2, 3]}
269+
assert fake_object.attr1 == "hello"
270+
# New attribute is in `attributes`
271+
fake_object.new_attrib = "spam"
272+
assert fake_object.attributes == {
273+
"attr1": "hello",
274+
"new_attrib": "spam",
275+
"alist": [1, 2, 3],
276+
}
277+
278+
279+
def test_attributes_is_copy(fake_object):
280+
# Modifying the dictionary does not cause modifications to the object
281+
result = fake_object.attributes
282+
result["alist"].append(10)
283+
assert result == {"attr1": "foo", "alist": [1, 2, 3, 10]}
284+
assert fake_object.attributes == {"attr1": "foo", "alist": [1, 2, 3]}
285+
286+
287+
def test_attributes_has_parent_attrs(fake_object_with_parent):
288+
assert fake_object_with_parent.attr1 == "foo"
289+
result = fake_object_with_parent.attributes
290+
assert result == {"attr1": "foo", "alist": [1, 2, 3], "test_id": "42"}
291+
292+
293+
def test_asdict(fake_object):
294+
assert fake_object.attr1 == "foo"
295+
result = fake_object.asdict()
296+
assert result == {"attr1": "foo", "alist": [1, 2, 3]}
297+
298+
299+
def test_asdict_no_parent_attrs(fake_object_with_parent):
300+
assert fake_object_with_parent.attr1 == "foo"
301+
result = fake_object_with_parent.asdict()
302+
assert result == {"attr1": "foo", "alist": [1, 2, 3]}
303+
assert "test_id" not in fake_object_with_parent.asdict()
304+
assert "test_id" not in fake_object_with_parent.asdict(with_parent_attrs=False)
305+
assert "test_id" in fake_object_with_parent.asdict(with_parent_attrs=True)
306+
307+
308+
def test_asdict_modify_dict_does_not_change_object(fake_object):
309+
result = fake_object.asdict()
310+
# Demonstrate modifying the dictionary does not modify the object
311+
result["attr1"] = "testing"
312+
result["alist"].append(4)
313+
assert result == {"attr1": "testing", "alist": [1, 2, 3, 4]}
314+
assert fake_object.attr1 == "foo"
315+
assert fake_object.alist == [1, 2, 3]
316+
317+
318+
def test_asdict_modify_dict_does_not_change_object2(fake_object):
319+
# Modify attribute and then ensure modifying a list in the returned dict won't
320+
# modify the list in the object.
321+
fake_object.attr1 = [9, 7, 8]
322+
assert fake_object.asdict() == {
323+
"attr1": [9, 7, 8],
324+
"alist": [1, 2, 3],
325+
}
326+
result = fake_object.asdict()
327+
result["attr1"].append(1)
328+
assert fake_object.asdict() == {
329+
"attr1": [9, 7, 8],
330+
"alist": [1, 2, 3],
331+
}
332+
333+
334+
def test_asdict_modify_object(fake_object):
335+
# asdict() returns the updated value
336+
fake_object.attr1 = "spam"
337+
assert fake_object.asdict() == {"attr1": "spam", "alist": [1, 2, 3]}

0 commit comments

Comments
 (0)