Skip to content

Commit 09a973e

Browse files
authored
Merge pull request #1721 from python-gitlab/test/cli-coverage
test(cli): improve basic CLI coverage
2 parents 93a3893 + 381c748 commit 09a973e

15 files changed

+104
-34
lines changed

gitlab/cli.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def _parse_value(v: Any) -> Any:
178178
return v
179179

180180

181-
def docs() -> argparse.ArgumentParser:
181+
def docs() -> argparse.ArgumentParser: # pragma: no cover
182182
"""
183183
Provide a statically generated parser for sphinx only, so we don't need
184184
to provide dummy gitlab config for readthedocs.
@@ -208,15 +208,15 @@ def main() -> None:
208208
sys.exit(0)
209209
sys.exit(e)
210210
# We only support v4 API at this time
211-
if config.api_version not in ("4",):
211+
if config.api_version not in ("4",): # dead code # pragma: no cover
212212
raise ModuleNotFoundError(name=f"gitlab.v{config.api_version}.cli")
213213

214214
# Now we build the entire set of subcommands and do the complete parsing
215215
parser = _get_parser()
216216
try:
217217
import argcomplete # type: ignore
218218

219-
argcomplete.autocomplete(parser)
219+
argcomplete.autocomplete(parser) # pragma: no cover
220220
except Exception:
221221
pass
222222
args = parser.parse_args()

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ files = "."
1212
module = [
1313
"docs.*",
1414
"docs.ext.*",
15+
"tests.*",
1516
"tests.functional.*",
1617
"tests.functional.api.*",
1718
"tests.unit.*",

requirements-docker.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
-r requirements.txt
22
-r requirements-test.txt
33
docker-compose==1.29.2 # prevent inconsistent .env behavior from system install
4-
pytest-console-scripts
54
pytest-docker

requirements-test.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
coverage
22
httmock
3-
mock
43
pytest
4+
pytest-console-scripts==1.2.1
55
pytest-cov
66
responses

tests/conftest.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import pytest
2+
3+
4+
@pytest.fixture(scope="session")
5+
def test_dir(pytestconfig):
6+
return pytestconfig.rootdir / "tests"

tests/functional/api/test_users.py

+3-9
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,17 @@
33
https://docs.gitlab.com/ee/api/users.html
44
https://docs.gitlab.com/ee/api/users.html#delete-authentication-identity-from-user
55
"""
6-
import pytest
76
import requests
87

98

10-
@pytest.fixture(scope="session")
11-
def avatar_path(test_dir):
12-
return test_dir / "fixtures" / "avatar.png"
13-
14-
15-
def test_create_user(gl, avatar_path):
9+
def test_create_user(gl, fixture_dir):
1610
user = gl.users.create(
1711
{
1812
"email": "foo@bar.com",
1913
"username": "foo",
2014
"name": "foo",
2115
"password": "foo_password",
22-
"avatar": open(avatar_path, "rb"),
16+
"avatar": open(fixture_dir / "avatar.png", "rb"),
2317
}
2418
)
2519

@@ -29,7 +23,7 @@ def test_create_user(gl, avatar_path):
2923

3024
avatar_url = user.avatar_url.replace("gitlab.test", "localhost:8080")
3125
uploaded_avatar = requests.get(avatar_url).content
32-
assert uploaded_avatar == open(avatar_path, "rb").read()
26+
assert uploaded_avatar == open(fixture_dir / "avatar.png", "rb").read()
3327

3428

3529
def test_block_user(gl, user):

tests/functional/cli/test_cli.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import json
2+
3+
from gitlab import __version__
4+
5+
6+
def test_main_entrypoint(script_runner, gitlab_config):
7+
ret = script_runner.run("python", "-m", "gitlab", "--config-file", gitlab_config)
8+
assert ret.returncode == 2
9+
10+
11+
def test_version(script_runner):
12+
ret = script_runner.run("gitlab", "--version")
13+
assert ret.stdout.strip() == __version__
14+
15+
16+
def test_invalid_config(script_runner):
17+
ret = script_runner.run("gitlab", "--gitlab", "invalid")
18+
assert not ret.success
19+
assert not ret.stdout
20+
21+
22+
def test_invalid_config_prints_help(script_runner):
23+
ret = script_runner.run("gitlab", "--gitlab", "invalid", "--help")
24+
assert ret.success
25+
assert ret.stdout
26+
27+
28+
def test_invalid_api_version(script_runner, monkeypatch, fixture_dir):
29+
monkeypatch.setenv("PYTHON_GITLAB_CFG", str(fixture_dir / "invalid_version.cfg"))
30+
ret = script_runner.run("gitlab", "--gitlab", "test", "project", "list")
31+
assert not ret.success
32+
assert ret.stderr.startswith("Unsupported API version:")
33+
34+
35+
def test_invalid_auth_config(script_runner, monkeypatch, fixture_dir):
36+
monkeypatch.setenv("PYTHON_GITLAB_CFG", str(fixture_dir / "invalid_auth.cfg"))
37+
ret = script_runner.run("gitlab", "--gitlab", "test", "project", "list")
38+
assert not ret.success
39+
assert "401" in ret.stderr
40+
41+
42+
def test_fields(gitlab_cli, project_file):
43+
cmd = "-o", "json", "--fields", "default_branch", "project", "list"
44+
45+
ret = gitlab_cli(cmd)
46+
assert ret.success
47+
48+
content = json.loads(ret.stdout.strip())
49+
assert ["default_branch" in item for item in content]

tests/functional/conftest.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
import gitlab
1010

1111

12+
@pytest.fixture(scope="session")
13+
def fixture_dir(test_dir):
14+
return test_dir / "functional" / "fixtures"
15+
16+
1217
def reset_gitlab(gl):
1318
# previously tools/reset_gitlab.py
1419
for project in gl.projects.list():
@@ -26,8 +31,8 @@ def reset_gitlab(gl):
2631
user.delete(hard_delete=True)
2732

2833

29-
def set_token(container, rootdir):
30-
set_token_rb = rootdir / "fixtures" / "set_token.rb"
34+
def set_token(container, fixture_dir):
35+
set_token_rb = fixture_dir / "set_token.rb"
3136

3237
with open(set_token_rb, "r") as f:
3338
set_token_command = f.read().strip()
@@ -68,13 +73,8 @@ def temp_dir():
6873

6974

7075
@pytest.fixture(scope="session")
71-
def test_dir(pytestconfig):
72-
return pytestconfig.rootdir / "tests" / "functional"
73-
74-
75-
@pytest.fixture(scope="session")
76-
def docker_compose_file(test_dir):
77-
return test_dir / "fixtures" / "docker-compose.yml"
76+
def docker_compose_file(fixture_dir):
77+
return fixture_dir / "docker-compose.yml"
7878

7979

8080
@pytest.fixture(scope="session")
@@ -129,15 +129,15 @@ def _wait(timeout=30, step=0.5):
129129

130130

131131
@pytest.fixture(scope="session")
132-
def gitlab_config(check_is_alive, docker_ip, docker_services, temp_dir, test_dir):
132+
def gitlab_config(check_is_alive, docker_ip, docker_services, temp_dir, fixture_dir):
133133
config_file = temp_dir / "python-gitlab.cfg"
134134
port = docker_services.port_for("gitlab", 80)
135135

136136
docker_services.wait_until_responsive(
137137
timeout=200, pause=5, check=lambda: check_is_alive("gitlab-test")
138138
)
139139

140-
token = set_token("gitlab-test", rootdir=test_dir)
140+
token = set_token("gitlab-test", fixture_dir=fixture_dir)
141141

142142
config = f"""[global]
143143
default = local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[test]
2+
url = https://gitlab.com
3+
private_token = abc123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[test]
2+
api_version = 3
3+
url = https://gitlab.example.com

tests/unit/conftest.py

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
import gitlab
44

55

6+
@pytest.fixture(scope="session")
7+
def fixture_dir(test_dir):
8+
return test_dir / "unit" / "fixtures"
9+
10+
611
@pytest.fixture
712
def gl():
813
return gitlab.Gitlab(
File renamed without changes.

tests/unit/objects/test_todos.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@
33
"""
44

55
import json
6-
import os
76

87
import pytest
98
import responses
109

1110
from gitlab.v4.objects import Todo
1211

13-
with open(f"{os.path.dirname(__file__)}/../data/todo.json", "r") as json_file:
14-
todo_content = json_file.read()
15-
json_content = json.loads(todo_content)
12+
13+
@pytest.fixture()
14+
def json_content(fixture_dir):
15+
with open(fixture_dir / "todo.json", "r") as json_file:
16+
todo_content = json_file.read()
17+
return json.loads(todo_content)
1618

1719

1820
@pytest.fixture
19-
def resp_todo():
21+
def resp_todo(json_content):
2022
with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
2123
rsps.add(
2224
method=responses.GET,

tests/unit/test_cli.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import pytest
2626

2727
from gitlab import cli
28+
from gitlab.exceptions import GitlabError
2829

2930

3031
@pytest.mark.parametrize(
@@ -66,12 +67,19 @@ def test_cls_to_what(class_name, expected_what):
6667
assert cli.cls_to_what(TestClass) == expected_what
6768

6869

69-
def test_die():
70+
@pytest.mark.parametrize(
71+
"message,error,expected",
72+
[
73+
("foobar", None, "foobar\n"),
74+
("foo", GitlabError("bar"), "foo (bar)\n"),
75+
],
76+
)
77+
def test_die(message, error, expected):
7078
fl = io.StringIO()
7179
with redirect_stderr(fl):
7280
with pytest.raises(SystemExit) as test:
73-
cli.die("foobar")
74-
assert fl.getvalue() == "foobar\n"
81+
cli.die(message, error)
82+
assert fl.getvalue() == expected
7583
assert test.value.code == 1
7684

7785

tests/unit/test_config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import io
1919
import os
2020
from textwrap import dedent
21+
from unittest import mock
2122

22-
import mock
2323
import pytest
2424

2525
from gitlab import config, USER_AGENT

0 commit comments

Comments
 (0)