pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python-gitlab/python-gitlab/commit/df072e130aa145a368bbdd10be98208a25100f89

test(gitlab): increase unit test coverage · python-gitlab/python-gitlab@df072e1 · GitHub
Skip to content

Commit df072e1

Browse files
nejchJohnVillalovos
authored andcommitted
test(gitlab): increase unit test coverage
1 parent c51b538 commit df072e1

12 files changed

Lines changed: 304 additions & 34 deletions

File tree

gitlab/client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,9 @@ def __setstate__(self, state: Dict[str, Any]) -> None:
208208
self.__dict__.update(state)
209209
# We only support v4 API at this time
210210
if self._api_version not in ("4",):
211-
raise ModuleNotFoundError(name=f"gitlab.v{self._api_version}.objects")
211+
raise ModuleNotFoundError(
212+
name=f"gitlab.v{self._api_version}.objects"
213+
) # pragma: no cover, dead code currently
212214
# NOTE: We must delay import of gitlab.v4.objects until now or
213215
# otherwise it will cause circular import errors
214216
import gitlab.v4.objects

gitlab/config.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def _parse_config(self) -> None:
154154
# CA bundle.
155155
try:
156156
self.ssl_verify = _config.get("global", "ssl_verify")
157-
except Exception:
157+
except Exception: # pragma: no cover
158158
pass
159159
except Exception:
160160
pass
@@ -166,7 +166,7 @@ def _parse_config(self) -> None:
166166
# CA bundle.
167167
try:
168168
self.ssl_verify = _config.get(self.gitlab_id, "ssl_verify")
169-
except Exception:
169+
except Exception: # pragma: no cover
170170
pass
171171
except Exception:
172172
pass
@@ -197,7 +197,9 @@ def _parse_config(self) -> None:
197197

198198
try:
199199
self.http_username = _config.get(self.gitlab_id, "http_username")
200-
self.http_password = _config.get(self.gitlab_id, "http_password")
200+
self.http_password = _config.get(
201+
self.gitlab_id, "http_password"
202+
) # pragma: no cover
201203
except Exception:
202204
pass
203205

tests/functional/cli/test_cli.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ def test_version(script_runner):
2727
assert ret.stdout.strip() == __version__
2828

2929

30+
def test_config_error_with_help_prints_help(script_runner):
31+
ret = script_runner.run("gitlab", "-c", "invalid-file", "--help")
32+
assert ret.stdout.startswith("usage:")
33+
assert ret.returncode == 0
34+
35+
3036
@pytest.mark.script_launch_mode("inprocess")
3137
@responses.activate
3238
def test_defaults_to_gitlab_com(script_runner, resp_get_project, monkeypatch):

tests/unit/helpers.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from typing import Optional
55

66
import requests
7+
import responses
8+
9+
MATCH_EMPTY_QUERY_PARAMS = [responses.matchers.query_param_matcher({})]
710

811

912
# NOTE: The function `httmock_response` and the class `Headers` is taken from

tests/unit/mixins/test_mixin_methods.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,17 @@ class M(ListMixin, FakeManager):
9797
pass
9898

9999
url = "http://localhost/api/v4/tests"
100+
headers = {
101+
"X-Page": "1",
102+
"X-Next-Page": "2",
103+
"X-Per-Page": "1",
104+
"X-Total-Pages": "2",
105+
"X-Total": "2",
106+
"Link": ("<http://localhost/api/v4/tests" ' rel="next"'),
107+
}
100108
responses.add(
101109
method=responses.GET,
110+
headers=headers,
102111
url=url,
103112
json=[{"id": 42, "foo": "bar"}, {"id": 43, "foo": "baz"}],
104113
status=200,
@@ -109,6 +118,14 @@ class M(ListMixin, FakeManager):
109118
mgr = M(gl)
110119
obj_list = mgr.list(iterator=True)
111120
assert isinstance(obj_list, base.RESTObjectList)
121+
assert obj_list.current_page == 1
122+
assert obj_list.prev_page is None
123+
assert obj_list.next_page == 2
124+
assert obj_list.per_page == 1
125+
assert obj_list.total == 2
126+
assert obj_list.total_pages == 2
127+
assert len(obj_list) == 2
128+
112129
for obj in obj_list:
113130
assert isinstance(obj, FakeObject)
114131
assert obj.id in (42, 43)
@@ -254,6 +271,25 @@ class M(UpdateMixin, FakeManager):
254271
assert responses.assert_call_count(url, 1) is True
255272

256273

274+
@responses.activate
275+
def test_update_mixin_uses_post(gl):
276+
class M(UpdateMixin, FakeManager):
277+
_update_uses_post = True
278+
279+
url = "http://localhost/api/v4/tests/1"
280+
responses.add(
281+
method=responses.POST,
282+
url=url,
283+
json={},
284+
status=200,
285+
match=[responses.matchers.query_param_matcher({})],
286+
)
287+
288+
mgr = M(gl)
289+
mgr.update(1, {})
290+
assert responses.assert_call_count(url, 1) is True
291+
292+
257293
@responses.activate
258294
def test_update_mixin_no_id(gl):
259295
class M(UpdateMixin, FakeManager):
@@ -323,6 +359,25 @@ class TestClass(SaveMixin, base.RESTObject):
323359
assert responses.assert_call_count(url, 1) is True
324360

325361

362+
@responses.activate
363+
def test_save_mixin_without_new_data(gl):
364+
class M(UpdateMixin, FakeManager):
365+
pass
366+
367+
class TestClass(SaveMixin, base.RESTObject):
368+
pass
369+
370+
url = "http://localhost/api/v4/tests/1"
371+
responses.add(method=responses.PUT, url=url)
372+
373+
mgr = M(gl)
374+
obj = TestClass(mgr, {"id": 1, "foo": "bar"})
375+
obj.save()
376+
377+
assert obj._attrs["foo"] == "bar"
378+
assert responses.assert_call_count(url, 0) is True
379+
380+
326381
@responses.activate
327382
def test_set_mixin(gl):
328383
class M(SetMixin, FakeManager):

tests/unit/test_base.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,15 @@ class MGR(base.RESTManager):
7878

7979
class TestRESTObject:
8080
def test_instantiate(self, fake_gitlab, fake_manager):
81-
obj = FakeObject(fake_manager, {"foo": "bar"})
81+
attrs = {"foo": "bar"}
82+
obj = FakeObject(fake_manager, attrs.copy())
8283

83-
assert {"foo": "bar"} == obj._attrs
84+
assert attrs == obj._attrs
8485
assert {} == obj._updated_attrs
8586
assert obj._create_managers() is None
8687
assert fake_manager == obj.manager
8788
assert fake_gitlab == obj.manager.gitlab
89+
assert str(obj) == f"{type(obj)} => {attrs}"
8890

8991
def test_instantiate_non_dict(self, fake_gitlab, fake_manager):
9092
with pytest.raises(gitlab.exceptions.GitlabParsingError):
@@ -201,6 +203,7 @@ def test_equality(self, fake_manager):
201203
obj1 = FakeObject(fake_manager, {"id": "foo"})
202204
obj2 = FakeObject(fake_manager, {"id": "foo", "other_attr": "bar"})
203205
assert obj1 == obj2
206+
assert len(set((obj1, obj2))) == 1
204207

205208
def test_equality_custom_id(self, fake_manager):
206209
class OtherFakeObject(FakeObject):
@@ -210,6 +213,11 @@ class OtherFakeObject(FakeObject):
210213
obj2 = OtherFakeObject(fake_manager, {"foo": "bar", "other_attr": "baz"})
211214
assert obj1 == obj2
212215

216+
def test_equality_no_id(self, fake_manager):
217+
obj1 = FakeObject(fake_manager, {"attr1": "foo"})
218+
obj2 = FakeObject(fake_manager, {"attr1": "bar"})
219+
assert not obj1 == obj2
220+
213221
def test_inequality(self, fake_manager):
214222
obj1 = FakeObject(fake_manager, {"id": "foo"})
215223
obj2 = FakeObject(fake_manager, {"id": "bar"})
@@ -219,6 +227,12 @@ def test_inequality_no_id(self, fake_manager):
219227
obj1 = FakeObject(fake_manager, {"attr1": "foo"})
220228
obj2 = FakeObject(fake_manager, {"attr1": "bar"})
221229
assert obj1 != obj2
230+
assert len(set((obj1, obj2))) == 2
231+
232+
def test_equality_with_other_objects(self, fake_manager):
233+
obj1 = FakeObject(fake_manager, {"id": "foo"})
234+
obj2 = None
235+
assert not obj1 == obj2
222236

223237
def test_dunder_str(self, fake_manager):
224238
fake_object = FakeObject(fake_manager, {"attr1": "foo"})
@@ -280,3 +294,11 @@ def test_pprint(self, capfd, fake_manager):
280294
" 'ham': 'eggseggseggseggseggseggseggseggseggseggseggseggseggseggseggs'}\n"
281295
)
282296
assert stderr == ""
297+
298+
def test_repr(self, fake_manager):
299+
attrs = {"attr1": "foo"}
300+
obj = FakeObject(fake_manager, attrs)
301+
assert repr(obj) == "<FakeObject id:None>"
302+
303+
FakeObject._id_attr = None
304+
assert repr(obj) == "<FakeObject>"

tests/unit/test_config.py

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@
5454
oauth_token = STUV
5555
"""
5656

57+
ssl_verify_str_config = """[global]
58+
default = one
59+
ssl_verify = /etc/ssl/certs/ca-certificates.crt
60+
61+
[one]
62+
url = http://one.url
63+
private_token = ABCDEF
64+
"""
65+
5766
custom_user_agent_config = f"""[global]
5867
default = one
5968
user_agent = {custom_user_agent}
@@ -69,7 +78,7 @@
6978
private_token = ABCDEF
7079
"""
7180

72-
missing_attr_config = """[global]
81+
invalid_data_config = """[global]
7382
[one]
7483
url = http://one.url
7584
@@ -83,6 +92,11 @@
8392
url = http://four.url
8493
private_token = ABCDEF
8594
per_page = 200
95+
96+
[invalid-api-version]
97+
url = http://invalid-api-version.url
98+
private_token = ABCDEF
99+
api_version = 1
86100
"""
87101

88102

@@ -173,7 +187,7 @@ def test_invalid_id(m_open, mock_clean_env, monkeypatch):
173187

174188
@mock.patch("builtins.open")
175189
def test_invalid_data(m_open, monkeypatch):
176-
fd = io.StringIO(missing_attr_config)
190+
fd = io.StringIO(invalid_data_config)
177191
fd.close = mock.Mock(return_value=None, side_effect=lambda: fd.seek(0))
178192
m_open.return_value = fd
179193

@@ -185,9 +199,14 @@ def test_invalid_data(m_open, monkeypatch):
185199
config.GitlabConfigParser(gitlab_id="two")
186200
with pytest.raises(config.GitlabDataError):
187201
config.GitlabConfigParser(gitlab_id="three")
188-
with pytest.raises(config.GitlabDataError) as emgr:
202+
203+
with pytest.raises(config.GitlabDataError) as e:
189204
config.GitlabConfigParser("four")
190-
assert "Unsupported per_page number: 200" == emgr.value.args[0]
205+
assert str(e.value) == "Unsupported per_page number: 200"
206+
207+
with pytest.raises(config.GitlabDataError) as e:
208+
config.GitlabConfigParser("invalid-api-version")
209+
assert str(e.value) == "Unsupported API version: 1"
191210

192211

193212
@mock.patch("builtins.open")
@@ -248,6 +267,18 @@ def test_valid_data(m_open, monkeypatch):
248267
assert cp.ssl_verify is True
249268

250269

270+
@mock.patch("builtins.open")
271+
def test_ssl_verify_as_str(m_open, monkeypatch):
272+
fd = io.StringIO(ssl_verify_str_config)
273+
fd.close = mock.Mock(return_value=None)
274+
m_open.return_value = fd
275+
276+
with monkeypatch.context() as m:
277+
m.setattr(Path, "resolve", _mock_existent_file)
278+
cp = config.GitlabConfigParser()
279+
assert cp.ssl_verify == "/etc/ssl/certs/ca-certificates.crt"
280+
281+
251282
@mock.patch("builtins.open")
252283
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
253284
def test_data_from_helper(m_open, monkeypatch, tmp_path):
@@ -286,6 +317,33 @@ def test_data_from_helper(m_open, monkeypatch, tmp_path):
286317
assert "secret" == cp.oauth_token
287318

288319

320+
@mock.patch("builtins.open")
321+
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
322+
def test_from_helper_subprocess_error_raises_error(m_open, monkeypatch):
323+
# using /usr/bin/false here to force a non-zero return code
324+
fd = io.StringIO(
325+
dedent(
326+
"""\
327+
[global]
328+
default = helper
329+
330+
[helper]
331+
url = https://helper.url
332+
oauth_token = helper: /usr/bin/false
333+
"""
334+
)
335+
)
336+
337+
fd.close = mock.Mock(return_value=None)
338+
m_open.return_value = fd
339+
with monkeypatch.context() as m:
340+
m.setattr(Path, "resolve", _mock_existent_file)
341+
with pytest.raises(config.GitlabConfigHelperError) as e:
342+
config.GitlabConfigParser(gitlab_id="helper")
343+
344+
assert "Failed to read oauth_token value from helper" in str(e.value)
345+
346+
289347
@mock.patch("builtins.open")
290348
@pytest.mark.parametrize(
291349
"config_string,expected_agent",

tests/unit/test_exceptions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
from gitlab import exceptions
44

55

6+
@pytest.mark.parametrize(
7+
"kwargs,expected",
8+
[
9+
({"error_message": "foo"}, "foo"),
10+
({"error_message": "foo", "response_code": "400"}, "400: foo"),
11+
],
12+
)
13+
def test_gitlab_error(kwargs, expected):
14+
error = exceptions.GitlabError(**kwargs)
15+
assert str(error) == expected
16+
17+
618
def test_error_raises_from_http_error():
719
"""Methods decorated with @on_http_error should raise from GitlabHttpError."""
820

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy