Skip to content

Commit 5a72a8a

Browse files
committed
feat: tests for CLIBase class
1 parent b3c59d0 commit 5a72a8a

File tree

1 file changed

+126
-3
lines changed

1 file changed

+126
-3
lines changed

test/script_tools.py

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@
3636
import getpass
3737
import mock
3838

39+
from mock import MagicMock, patch
3940
from vsc.install.testing import TestCase
40-
from vsc.utils.nagios import NAGIOS_EXIT_WARNING
41-
from vsc.utils.script_tools import ExtendedSimpleOption, DEFAULT_OPTIONS, NrpeCLI, CLI
41+
42+
from vsc.install.testing import TestCase
43+
from vsc.utils.nagios import NAGIOS_EXIT_WARNING, NagiosStatusMixin
44+
from vsc.utils.script_tools import (
45+
ExtendedSimpleOption, DEFAULT_OPTIONS, NrpeCLI, CLI,
46+
CLIBase, LockMixin, HAMixin, TimestampMixin)
47+
4248

4349
class TestExtendedSimpleOption(TestCase):
4450
"""
@@ -101,7 +107,7 @@ class MyNrpeCLI(NrpeCLI):
101107
CLI_OPTIONS = {
102108
'magic': ('some magic', None, 'store', 'magicdef'),
103109
}
104-
def do(self, _):
110+
def do(self,dryrun):
105111
return magic.go()
106112

107113

@@ -230,3 +236,120 @@ def test_exit(self, locklock, releaselock):
230236
with mock.patch('sys.exit', fake_exit):
231237
cli.warning("be warned")
232238
fake_exit.assert_called_with(1)
239+
240+
241+
class TestCLIBase(TestCase):
242+
def setUp(self):
243+
"""
244+
Set up mock instances and common configurations.
245+
"""
246+
super().setUp()
247+
248+
# Redirect stdout/stderr to prevent TestCase conflicts
249+
self.orig_sys_stdout = sys.stdout
250+
self.orig_sys_stderr = sys.stderr
251+
sys.stdout = MagicMock()
252+
sys.stderr = MagicMock()
253+
254+
# Create a dummy subclass of CLIBase for testing
255+
class TestCLI(CLIBase):
256+
CLI_OPTIONS = {
257+
'test-option': ('Test description', None, 'store_true', False),
258+
}
259+
260+
def do(self, dryrun=False):
261+
if dryrun:
262+
return ["Dry run mode active."]
263+
return []
264+
265+
self.cli = TestCLI(name="Test CLI")
266+
267+
@patch('vsc.utils.script_tools.ArgParser.parse_args', return_value=MagicMock(dry_run=False))
268+
@patch('vsc.utils.script_tools.logging.info')
269+
def test_main_basic(self, mock_logging_info, mock_parse_args):
270+
"""
271+
Test the main method without any mixins.
272+
"""
273+
self.cli.main()
274+
self.assertEqual(self.cli.name, "Test CLI")
275+
#mock_logging_info.assert_any_call("Test CLI started.")
276+
277+
def test_get_options(self):
278+
"""
279+
Test the get_options method aggregates CLI options.
280+
"""
281+
options = self.cli.get_options()
282+
self.assertIn('test-option', options)
283+
284+
@patch('vsc.utils.script_tools.logging.error')
285+
@patch('vsc.utils.script_tools.sys.exit')
286+
def test_critical_no_nagios(self, mock_sys_exit, mock_logging_error):
287+
"""
288+
Test critical method behavior without NagiosStatusMixin.
289+
"""
290+
self.cli.critical("Critical error")
291+
mock_logging_error.assert_called_with("Critical error")
292+
mock_sys_exit.assert_called_with(1)
293+
294+
@patch('vsc.utils.script_tools.logging.info')
295+
@patch('vsc.utils.script_tools.ArgParser.parse_args', return_value=MagicMock(dry_run=False))
296+
def test_main_with_dry_run(self, mock_parse_args, mock_logging_info):
297+
"""
298+
Test the main method in dry-run mode.
299+
"""
300+
self.cli.main()
301+
#mock_logging_info.assert_any_call("Test CLI (dry-run) started.")
302+
303+
@patch('vsc.utils.script_tools.logging.info')
304+
@patch('vsc.utils.script_tools.ArgParser.parse_args', return_value=MagicMock(dry_run=False))
305+
def test_main_with_mixins(self, mock_parse_args, mock_logging_info):
306+
"""
307+
Test the main method with mixins applied.
308+
"""
309+
# Extend TestCLI with mixins
310+
class TestCLIMixins(CLIBase, NagiosStatusMixin, LockMixin):
311+
CLI_OPTIONS = {'test-mixin-option': ('Mixin test description', None, 'store_true', False)}
312+
313+
def do(self, dryrun=False):
314+
return []
315+
316+
def nagios_prologue(self):
317+
self.nagios_prologue_called = True
318+
319+
def lock_prologue(self):
320+
self.lock_prologue_called = True
321+
322+
def nagios_epilogue(self):
323+
self.nagios_epilogue_called = True
324+
325+
def lock_epilogue(self):
326+
self.lock_epilogue_called = True
327+
328+
cli = TestCLIMixins(name="Test CLI with Mixins")
329+
cli.nagios_prologue_called = False
330+
cli.lock_prologue_called = False
331+
cli.nagios_epilogue_called = False
332+
cli.lock_epilogue_called = False
333+
334+
cli.main()
335+
336+
self.assertTrue(cli.nagios_prologue_called)
337+
self.assertTrue(cli.lock_prologue_called)
338+
self.assertTrue(cli.nagios_epilogue_called)
339+
self.assertTrue(cli.lock_epilogue_called)
340+
341+
@patch('vsc.utils.script_tools.logging.error')
342+
@patch('vsc.utils.script_tools.sys.exit')
343+
def test_main_critical_exception(self, mock_sys_exit, mock_logging_error):
344+
"""
345+
Test the main method when a critical exception is raised.
346+
"""
347+
class FailingCLI(CLIBase):
348+
def do(self, dryrun=False):
349+
raise Exception("Unrecoverable error!")
350+
351+
cli = FailingCLI("Failing CLI")
352+
353+
cli.main()
354+
mock_logging_error.assert_called_with("Script failed in an unrecoverable way: Unrecoverable error!")
355+
mock_sys_exit.assert_called_with(1)

0 commit comments

Comments
 (0)