Skip to content

Commit 129c564

Browse files
committed
Migrate test suite from oslotest/stestr to pytest
Remove legacy OpenStack testing infrastructure and modernize the test suite using pytest fixtures and assertions. This simplifies dependencies and provides a more modern testing experience. Changes: - Remove .stestr.conf configuration file - Replace oslotest base classes with pytest fixtures in clibase.py - Convert unittest assertions to pytest style (assertEqual -> assert) - Add conftest.py with shared fixtures for mock client - Update pyproject.toml to remove oslotest/testtools/fixtures deps - Update tox.ini to use pytest instead of stestr
1 parent 8c1f8c3 commit 129c564

13 files changed

Lines changed: 226 additions & 200 deletions

.stestr.conf

Lines changed: 0 additions & 3 deletions
This file was deleted.

gerritclient/tests/conftest.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Pytest fixtures for gerritclient tests."""
2+
3+
import shlex
4+
from unittest import mock
5+
6+
import pytest
7+
8+
from gerritclient import client
9+
from gerritclient import main as main_mod
10+
11+
12+
@pytest.fixture
13+
def mock_client():
14+
"""Fixture that provides a mocked gerrit client."""
15+
with mock.patch.object(client, "get_client") as m_get_client:
16+
m_client = mock.MagicMock()
17+
m_get_client.return_value = m_client
18+
yield {"get_client": m_get_client, "client": m_client}
19+
20+
21+
def exec_command(command=""):
22+
"""Executes gerrit with the specified arguments."""
23+
argv = shlex.split(command)
24+
if "--debug" not in argv:
25+
argv = [*argv, "--debug"]
26+
return main_mod.main(argv=argv)
Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
1+
"""Base class for CLI tests using pytest."""
2+
13
import shlex
24
from unittest import mock
35

4-
from oslotest import base as oslo_base
6+
import pytest
57

68
from gerritclient import client
79
from gerritclient import main as main_mod
810

911

10-
class BaseCLITest(oslo_base.BaseTestCase):
12+
class BaseCLITest:
1113
"""Base class for testing CLI."""
1214

13-
def setUp(self):
14-
super().setUp()
15-
16-
self._get_client_patcher = mock.patch.object(client, "get_client")
17-
self.m_get_client = self._get_client_patcher.start()
18-
19-
self.m_client = mock.MagicMock()
20-
self.m_get_client.return_value = self.m_client
21-
self.addCleanup(self._get_client_patcher.stop)
15+
@pytest.fixture(autouse=True)
16+
def setup_client_mock(self):
17+
"""Set up mocked client for each test."""
18+
with mock.patch.object(client, "get_client") as m_get_client:
19+
self.m_client = mock.MagicMock()
20+
m_get_client.return_value = self.m_client
21+
self.m_get_client = m_get_client
22+
yield
2223

2324
@staticmethod
2425
def exec_command(command=""):
2526
"""Executes gerrit with the specified arguments."""
26-
2727
argv = shlex.split(command)
2828
if "--debug" not in argv:
2929
argv = [*argv, "--debug"]
30-
3130
return main_mod.main(argv=argv)

gerritclient/tests/unit/cli/test_account.py

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1+
"""Tests for gerrit account commands."""
2+
13
import json
24
from unittest import mock
35

6+
import pytest
7+
48
from gerritclient.tests.unit.cli import clibase
59
from gerritclient.tests.utils import fake_account, fake_sshkeyinfo
610

711

812
class TestAccountCommand(clibase.BaseCLITest):
913
"""Tests for gerrit account * commands."""
1014

11-
def setUp(self):
12-
super().setUp()
15+
@pytest.fixture(autouse=True)
16+
def setup_account_mocks(self, setup_client_mock):
17+
"""Set up account-specific mocks."""
1318
self.m_client.get_all.return_value = fake_account.get_fake_accounts(10)
1419
self.m_client.get_by_id.return_value = fake_account.get_fake_account()
1520

@@ -74,10 +79,9 @@ def test_account_show(self):
7479
@mock.patch("sys.stderr")
7580
def test_account_show_fail(self, mocked_stderr):
7681
args = "account show"
77-
self.assertRaises(SystemExit, self.exec_command, args)
78-
self.assertIn(
79-
"account show: error:", mocked_stderr.write.call_args_list[-1][0][0]
80-
)
82+
with pytest.raises(SystemExit):
83+
self.exec_command(args)
84+
assert "account show: error:" in mocked_stderr.write.call_args_list[-1][0][0]
8185

8286
def test_account_show_w_details(self):
8387
account_id = "john"
@@ -125,19 +129,18 @@ def test_account_create_w_parameters_from_bad_file_format_fail(self, mocked_stde
125129
m_open = mock.mock_open(read_data=json.dumps(test_data))
126130
with mock.patch("gerritclient.common.utils.open", m_open, create=True):
127131
result = self.exec_command(args)
128-
self.assertEqual(1, result)
132+
assert result == 1
129133
stderr_output = "".join(
130134
call[0][0] for call in mocked_stderr.write.call_args_list
131135
)
132-
self.assertIn("Unsupported data format", stderr_output)
136+
assert "Unsupported data format" in stderr_output
133137

134138
@mock.patch("sys.stderr")
135139
def test_account_create_fail(self, mocked_stderr):
136140
args = "account create"
137-
self.assertRaises(SystemExit, self.exec_command, args)
138-
self.assertIn(
139-
"account create: error:", mocked_stderr.write.call_args_list[-1][0][0]
140-
)
141+
with pytest.raises(SystemExit):
142+
self.exec_command(args)
143+
assert "account create: error:" in mocked_stderr.write.call_args_list[-1][0][0]
141144

142145
def test_account_set_fullname(self):
143146
account_id = "69"
@@ -196,10 +199,11 @@ def test_account_status_show(self):
196199
@mock.patch("sys.stderr")
197200
def test_account_status_show_fail(self, mocked_stderr):
198201
args = "account status show"
199-
self.assertRaises(SystemExit, self.exec_command, args)
200-
self.assertIn(
201-
"run account status show: error:",
202-
mocked_stderr.write.call_args_list[-1][0][0],
202+
with pytest.raises(SystemExit):
203+
self.exec_command(args)
204+
assert (
205+
"account status show: error:"
206+
in mocked_stderr.write.call_args_list[-1][0][0]
203207
)
204208

205209
def test_account_status_set(self):
@@ -216,10 +220,11 @@ def test_account_status_set(self):
216220
@mock.patch("sys.stderr")
217221
def test_account_status_set_fail(self, mocked_stderr):
218222
args = "account status set"
219-
self.assertRaises(SystemExit, self.exec_command, args)
220-
self.assertIn(
221-
"run account status set: error:",
222-
mocked_stderr.write.call_args_list[-1][0][0],
223+
with pytest.raises(SystemExit):
224+
self.exec_command(args)
225+
assert (
226+
"account status set: error:"
227+
in mocked_stderr.write.call_args_list[-1][0][0]
223228
)
224229

225230
def test_account_set_password(self):
@@ -287,10 +292,9 @@ def test_account_ssh_key_show(self):
287292
def test_account_ssh_key_show_fail(self, mocked_stderr):
288293
account_id = "69"
289294
args = f"account ssh-key show {account_id}"
290-
self.assertRaises(SystemExit, self.exec_command, args)
291-
self.assertIn(
292-
"ssh-key show: error:", mocked_stderr.write.call_args_list[-1][0][0]
293-
)
295+
with pytest.raises(SystemExit):
296+
self.exec_command(args)
297+
assert "ssh-key show: error:" in mocked_stderr.write.call_args_list[-1][0][0]
294298

295299
def test_account_ssh_key_add(self):
296300
account_id = "69"
@@ -337,8 +341,9 @@ def test_account_ssh_key_add_fail_with_mutually_exclusive_params(
337341
"YImydZAw\u003d\u003d john.doe@example.com"
338342
)
339343
args = f'account ssh-key add {account_id} --ssh-key "{ssh_key}" --file {expected_path} '
340-
self.assertRaises(SystemExit, self.exec_command, args)
341-
self.assertIn("not allowed", mocked_stderr.write.call_args_list[-1][0][0])
344+
with pytest.raises(SystemExit):
345+
self.exec_command(args)
346+
assert "not allowed" in mocked_stderr.write.call_args_list[-1][0][0]
342347

343348
def test_account_ssh_key_delete(self):
344349
account_id = "69"
@@ -403,7 +408,8 @@ def test_account_oauth_access_token_show(self):
403408
@mock.patch("sys.stderr")
404409
def test_account_oauth_access_token_fail(self, mocked_stderr):
405410
args = "account oauth show"
406-
self.assertRaises(SystemExit, self.exec_command, args)
407-
self.assertIn(
408-
"account oauth show: error:", mocked_stderr.write.call_args_list[-1][0][0]
411+
with pytest.raises(SystemExit):
412+
self.exec_command(args)
413+
assert (
414+
"account oauth show: error:" in mocked_stderr.write.call_args_list[-1][0][0]
409415
)

gerritclient/tests/unit/cli/test_change.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import json
22
from unittest import mock
33

4+
import pytest
5+
46
from gerritclient.tests.unit.cli import clibase
57
from gerritclient.tests.utils import fake_account, fake_change, fake_comment
68

79

810
class TestChangeCommand(clibase.BaseCLITest):
911
"""Tests for gerrit change * commands."""
1012

11-
def setUp(self):
12-
super().setUp()
13-
1413
def test_change_list_w_single_query(self):
1514
query = ["status:open+is:watched"]
1615
args = "change list {query} --max-width 110".format(query="".join(query))
@@ -150,11 +149,11 @@ def test_change_create_bad_file_format_fail(self, mocked_stderr):
150149
m_open = mock.mock_open(read_data=json.dumps(test_data))
151150
with mock.patch("gerritclient.common.utils.open", m_open, create=True):
152151
result = self.exec_command(args)
153-
self.assertEqual(1, result)
152+
assert result == 1
154153
stderr_output = "".join(
155154
call[0][0] for call in mocked_stderr.write.call_args_list
156155
)
157-
self.assertIn("Unsupported data format", stderr_output)
156+
assert "Unsupported data format" in stderr_output
158157

159158
def test_change_delete(self):
160159
change_id = "I8473b95934b5732ac55d26311a706c9c2bde9940"
@@ -376,11 +375,9 @@ def test_change_robotcomments_list(self):
376375
def test_change_comments_list_w_wrong_type_fail(self, mocked_stderr):
377376
change_id = "I8473b95934b5732ac55d26311a706c9c2bde9940"
378377
args = f"change comment list {change_id} --type bad_comment"
379-
self.assertRaises(SystemExit, self.exec_command, args)
380-
self.assertIn(
381-
"invalid choice: 'bad_comment'",
382-
mocked_stderr.write.call_args_list[-1][0][0],
383-
)
378+
with pytest.raises(SystemExit):
379+
self.exec_command(args)
380+
assert "invalid choice: 'bad_comment'" in mocked_stderr.write.call_args_list[-1][0][0]
384381

385382
def test_change_consistency_check(self):
386383
change_id = "I8473b95934b5732ac55d26311a706c9c2bde9940"

gerritclient/tests/unit/cli/test_group.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import json
22
from unittest import mock
33

4+
import pytest
5+
46
from gerritclient.tests.unit.cli import clibase
57
from gerritclient.tests.utils import fake_account, fake_group
68

79

810
class TestGroupCommand(clibase.BaseCLITest):
911
"""Tests for gerrit group * commands."""
1012

11-
def setUp(self):
12-
super().setUp()
13+
@pytest.fixture(autouse=True)
14+
def setup_group_mocks(self, setup_client_mock):
15+
"""Set up group-specific mocks."""
1316
self.m_client.get_all.return_value = fake_group.get_fake_groups(10)
1417
get_fake_group = fake_group.get_fake_group()
1518
self.m_client.get_by_id.return_value = get_fake_group
@@ -94,19 +97,18 @@ def test_group_create_w_parameters_from_bad_file_format_fail(self, mocked_stderr
9497
m_open = mock.mock_open(read_data=json.dumps(test_data))
9598
with mock.patch("gerritclient.common.utils.open", m_open, create=True):
9699
result = self.exec_command(args)
97-
self.assertEqual(1, result)
100+
assert result == 1
98101
stderr_output = "".join(
99102
call[0][0] for call in mocked_stderr.write.call_args_list
100103
)
101-
self.assertIn("Unsupported data format", stderr_output)
104+
assert "Unsupported data format" in stderr_output
102105

103106
@mock.patch("sys.stderr")
104107
def test_group_project_fail(self, mocked_stderr):
105108
args = "group create"
106-
self.assertRaises(SystemExit, self.exec_command, args)
107-
self.assertIn(
108-
"group create: error:", mocked_stderr.write.call_args_list[-1][0][0]
109-
)
109+
with pytest.raises(SystemExit):
110+
self.exec_command(args)
111+
assert "group create: error:" in mocked_stderr.write.call_args_list[-1][0][0]
110112

111113
def test_group_rename(self):
112114
group_id = "69"
@@ -146,10 +148,9 @@ def test_group_set_options(self):
146148
def test_group_set_options_fail(self, mocked_stderr):
147149
group_id = "69"
148150
args = f"group options set {group_id} --visible --no-visible"
149-
self.assertRaises(SystemExit, self.exec_command, args)
150-
self.assertIn(
151-
"not allowed with argument", mocked_stderr.write.call_args_list[-1][0][0]
152-
)
151+
with pytest.raises(SystemExit):
152+
self.exec_command(args)
153+
assert "not allowed with argument" in mocked_stderr.write.call_args_list[-1][0][0]
153154

154155
def test_group_set_owner_group(self):
155156
group_id = "69"

gerritclient/tests/unit/cli/test_plugin.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import os
22
from unittest import mock
33

4+
import pytest
5+
46
from gerritclient.tests.unit.cli import clibase
57
from gerritclient.tests.utils import fake_plugin
68

79

810
class TestPluginCommand(clibase.BaseCLITest):
911
"""Tests for gerrit plugin * commands."""
1012

11-
def setUp(self):
12-
super().setUp()
13+
@pytest.fixture(autouse=True)
14+
def setup_plugin_mocks(self, setup_client_mock):
15+
"""Set up plugin-specific mocks."""
1316
self.m_client.get_all.return_value = fake_plugin.get_fake_plugins(10)
1417
get_fake_plugin = fake_plugin.get_fake_plugin(plugin_id="fake-plugin")
1518
self.m_client.get_by_id.return_value = get_fake_plugin
@@ -55,18 +58,16 @@ def test_plugin_disable(self):
5558
@mock.patch("sys.stderr")
5659
def test_plugin_enable_fail(self, mocked_stderr):
5760
args = "plugin enable"
58-
self.assertRaises(SystemExit, self.exec_command, args)
59-
self.assertIn(
60-
"plugin enable: error:", mocked_stderr.write.call_args_list[-1][0][0]
61-
)
61+
with pytest.raises(SystemExit):
62+
self.exec_command(args)
63+
assert "plugin enable: error:" in mocked_stderr.write.call_args_list[-1][0][0]
6264

6365
@mock.patch("sys.stderr")
6466
def test_plugin_disable_fail(self, mocked_stderr):
6567
args = "plugin disable"
66-
self.assertRaises(SystemExit, self.exec_command, args)
67-
self.assertIn(
68-
"plugin disable: error:", mocked_stderr.write.call_args_list[-1][0][0]
69-
)
68+
with pytest.raises(SystemExit):
69+
self.exec_command(args)
70+
assert "plugin disable: error:" in mocked_stderr.write.call_args_list[-1][0][0]
7071

7172
def test_plugin_reload(self):
7273
plugin_id = "fake-plugin"
@@ -112,8 +113,8 @@ def test_plugin_install_w_wrong_identifier_fail(self, mocked_stderr):
112113
url = "http://url/path/to/plugin.jar"
113114
args = f"plugin install {plugin_id} --url {url}"
114115
result = self.exec_command(args)
115-
self.assertEqual(1, result)
116+
assert result == 1
116117
stderr_output = "".join(
117118
call[0][0] for call in mocked_stderr.write.call_args_list
118119
)
119-
self.assertIn('Plugin identifier must contain ".jar"', stderr_output)
120+
assert 'Plugin identifier must contain ".jar"' in stderr_output

0 commit comments

Comments
 (0)