diff --git a/.coveragerc b/.coveragerc index 3419a43..1b91d48 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,5 @@ [run] omit = - unittests/ardupilot_methodic_configurator_unittest.py - unittests/backend_filesystem_unittest.py - unittests/frontend_tkinter_unittest.py + unittests/ardupilot_methodic_configurator_test.py + unittests/backend_filesystem_test.py + unittests/frontend_tkinter_test.py diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index f21681d..e78c9ee 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -34,15 +34,15 @@ jobs: - name: Test with unittest run: | - python -m unittest discover -s ./unittests -p '*_unittest.py' + python -m unittest discover -s ./unittests -p '*_test.py' - name: Unittest coverage report run: | cd unittests - python -m coverage run -m unittest annotate_params_unittest.py - python -m coverage run -m unittest ardupilot_methodic_configurator_unittest.py - python -m coverage run -m unittest backend_filesystem_unittest.py - python -m coverage run -m unittest extract_params_defaults_unittest.py - python -m coverage run -m unittest frontend_tkinter_unittest.py - python -m coverage run -m unittest param_pid_adjustment_update_unittest.py + python -m coverage run -m unittest annotate_params_test.py + python -m coverage run -m unittest ardupilot_methodic_configurator_test.py + python -m coverage run -m unittest backend_filesystem_test.py + python -m coverage run -m unittest extract_params_defaults_test.py + python -m coverage run -m unittest frontend_tkinter_test.py + python -m coverage run -m unittest param_pid_adjustment_update_test.py python -m coverage html diff --git a/MethodicConfigurator/extract_param_defaults.py b/MethodicConfigurator/extract_param_defaults.py index 080b503..778c43c 100644 --- a/MethodicConfigurator/extract_param_defaults.py +++ b/MethodicConfigurator/extract_param_defaults.py @@ -176,7 +176,7 @@ def output_params(params: Dict[str, float], format_type: str = 'missionplanner', if format_type == "qgcs": if sysid == -1: if 'SYSID_THISMAV' in params: - sysid = params['SYSID_THISMAV'] + sysid = int(params['SYSID_THISMAV']) else: sysid = 1 # if unspecified, default to 1 if compid == -1: diff --git a/pytest.ini b/pytest.ini index 39e25bc..8043ba1 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,5 +1,5 @@ [pytest] python_files = - unittests/*_unittest.py + unittests/*_test.py pythonpath = MethodicConfigurator -addopts = -v --strict-config --continue-on-collection-errors --cov-report=xml:unittests/coverage.xml --ignore=unittests/ardupilot_methodic_configurator_unittest.py --ignore=unittests/backend_filesystem_unittest.py --ignore=unittests/frontend_tkinter_unittest.py +addopts = -v --strict-config --continue-on-collection-errors --cov-report=xml:unittests/coverage.xml --ignore=unittests/ardupilot_methodic_configurator_test.py --ignore=unittests/backend_filesystem_test.py --ignore=unittests/frontend_tkinter_test.py diff --git a/unittests/annotate_params_test.py b/unittests/annotate_params_test.py old mode 100644 new mode 100755 index 537453c..e6b0a06 --- a/unittests/annotate_params_test.py +++ b/unittests/annotate_params_test.py @@ -19,14 +19,14 @@ import mock from annotate_params import get_xml_data -from annotate_params import remove_prefix -from annotate_params import split_into_lines -from annotate_params import create_doc_dict -from annotate_params import format_columns -from annotate_params import update_parameter_documentation -from annotate_params import print_read_only_params -from annotate_params import BASE_URL -from annotate_params import PARAM_DEFINITION_XML_FILE +from MethodicConfigurator.annotate_params import remove_prefix +from MethodicConfigurator.annotate_params import split_into_lines +from MethodicConfigurator.annotate_params import create_doc_dict +from MethodicConfigurator.annotate_params import format_columns +from MethodicConfigurator.annotate_params import update_parameter_documentation +from MethodicConfigurator.annotate_params import print_read_only_params +from MethodicConfigurator.annotate_params import BASE_URL +from MethodicConfigurator.annotate_params import PARAM_DEFINITION_XML_FILE class TestParamDocsUpdate(unittest.TestCase): diff --git a/unittests/annotate_params_test.sh b/unittests/annotate_params_test.sh old mode 100644 new mode 100755 index d40023f..8c9c60b --- a/unittests/annotate_params_test.sh +++ b/unittests/annotate_params_test.sh @@ -1,3 +1,3 @@ -python3 -m coverage run -m unittest annotate_params_unittest.py +PYTHONPATH=../MethodicConfigurator python3 -m coverage run -m unittest annotate_params_test.py python3 -m coverage html firefox htmlcov/annotate_params_py.html \ No newline at end of file diff --git a/unittests/ardupilot_methodic_configurator_test.py b/unittests/ardupilot_methodic_configurator_test.py old mode 100644 new mode 100755 index 40c6118..b0ca415 --- a/unittests/ardupilot_methodic_configurator_test.py +++ b/unittests/ardupilot_methodic_configurator_test.py @@ -15,7 +15,7 @@ from unittest.mock import patch # from unittest.mock import MagicMock # from unittest.mock import mock_open -from ardupilot_methodic_configurator import argument_parser +from MethodicConfigurator.ardupilot_methodic_configurator import argument_parser class TestArgumentParser(unittest.TestCase): diff --git a/unittests/backend_filesystem_test.py b/unittests/backend_filesystem_test.py old mode 100644 new mode 100755 index 7eb22fe..796c481 --- a/unittests/backend_filesystem_test.py +++ b/unittests/backend_filesystem_test.py @@ -12,14 +12,17 @@ import unittest # import os -from unittest.mock import patch, MagicMock -from backend_filesystem import LocalFilesystem +from unittest.mock import patch +from unittest.mock import MagicMock -class TestLocalFilesystem(unittest.TestCase): +from MethodicConfigurator.backend_filesystem import LocalFilesystem - @patch('backend_filesystem.os.path.isdir') - @patch('backend_filesystem.os.listdir') + +class TestLocalFilesystem(): + + @patch('os.path.isdir') + @patch('os.listdir') def test_read_params_from_files(self, mock_listdir, mock_isdir): # Setup mock_isdir.return_value = True @@ -48,8 +51,8 @@ def test_str_to_bool(self): self.assertFalse(lfs.str_to_bool('0')) self.assertIsNone(lfs.str_to_bool('maybe')) - @patch('backend_filesystem.os.path.isdir') - @patch('backend_filesystem.os.listdir') + @patch('os.path.isdir') + @patch('os.listdir') @patch('backend_filesystem.LocalFilesystem.read_params_from_files') def test_re_init(self, mock_read_params_from_files, mock_listdir, mock_isdir): mock_isdir.return_value = True @@ -82,5 +85,32 @@ def test_write_summary_files(self): pass +class TestCopyTemplateFilesToNewVehicleDir(): + + @patch('os.listdir') + @patch('os.path.join') + @patch('shutil.copytree') + @patch('shutil.copy2') + def test_copy_template_files_to_new_vehicle_dir(self, mock_copy2, mock_copytree, mock_join, mock_listdir): + # Ensure the mock for os.listdir returns the expected items + mock_listdir.return_value = ['file1', 'dir1'] + # Simulate os.path.join behavior to ensure paths are constructed as expected + mock_join.side_effect = lambda *args: '/'.join(args) + + # Initialize LocalFilesystem + lfs = LocalFilesystem('vehicle_dir', 'vehicle_type') + + # Call the method under test + lfs.copy_template_files_to_new_vehicle_dir('template_dir', 'new_vehicle_dir') + + # Assertions to verify the mocks were called as expected + mock_listdir.assert_called_once_with('template_dir') + mock_join.assert_any_call('template_dir', 'file1') + mock_join.assert_any_call('template_dir', 'dir1') + mock_join.assert_any_call('new_vehicle_dir', 'file1') + mock_join.assert_any_call('new_vehicle_dir', 'dir1') + mock_copy2.assert_called_once_with('template_dir/file1', 'new_vehicle_dir/file1') + mock_copytree.assert_called_once_with('template_dir/dir1', 'new_vehicle_dir/dir1') + if __name__ == '__main__': unittest.main() diff --git a/unittests/extract_param_defaults_test.py b/unittests/extract_param_defaults_test.py old mode 100644 new mode 100755 index 35ef6cf..5b505ea --- a/unittests/extract_param_defaults_test.py +++ b/unittests/extract_param_defaults_test.py @@ -9,17 +9,18 @@ # pylint: skip-file import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import patch +from unittest.mock import MagicMock -from extract_param_defaults import extract_parameter_values -from extract_param_defaults import missionplanner_sort -from extract_param_defaults import mavproxy_sort -from extract_param_defaults import sort_params -from extract_param_defaults import output_params -from extract_param_defaults import parse_arguments -from extract_param_defaults import NO_DEFAULT_VALUES_MESSAGE -from extract_param_defaults import MAVLINK_SYSID_MAX -from extract_param_defaults import MAVLINK_COMPID_MAX +from MethodicConfigurator.extract_param_defaults import extract_parameter_values +from MethodicConfigurator.extract_param_defaults import missionplanner_sort +from MethodicConfigurator.extract_param_defaults import mavproxy_sort +from MethodicConfigurator.extract_param_defaults import sort_params +from MethodicConfigurator.extract_param_defaults import output_params +from MethodicConfigurator.extract_param_defaults import parse_arguments +from MethodicConfigurator.extract_param_defaults import NO_DEFAULT_VALUES_MESSAGE +from MethodicConfigurator.extract_param_defaults import MAVLINK_SYSID_MAX +from MethodicConfigurator.extract_param_defaults import MAVLINK_COMPID_MAX class TestArgParseParameters(unittest.TestCase): @@ -181,7 +182,7 @@ def test_mavproxy_sort(self): class TestOutputParams(unittest.TestCase): - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 1.0, 'PARAM1': 2.0} @@ -191,9 +192,11 @@ def test_output_params(self, mock_print): # Check if the print function was called with the correct parameters expected_calls = [unittest.mock.call('PARAM2,1'), unittest.mock.call('PARAM1,2')] + print(mock_print.mock_calls) + print(expected_calls) mock_print.assert_has_calls(expected_calls, any_order=False) - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_missionplanner_non_numeric(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM1': 'non-numeric'} @@ -205,7 +208,7 @@ def test_output_params_missionplanner_non_numeric(self, mock_print): expected_calls = [unittest.mock.call('PARAM1,non-numeric')] mock_print.assert_has_calls(expected_calls, any_order=False) - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_mavproxy(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 2.0, 'PARAM1': 1.0} @@ -219,7 +222,7 @@ def test_output_params_mavproxy(self, mock_print): unittest.mock.call("%-15s %.6f" % ('PARAM2', 2.0))] mock_print.assert_has_calls(expected_calls, any_order=False) - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_qgcs(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 2.0, 'PARAM1': 1.0} @@ -234,7 +237,7 @@ def test_output_params_qgcs(self, mock_print): unittest.mock.call("%u %u %-15s %.6f %u" % (1, 1, 'PARAM2', 2.0, 9))] mock_print.assert_has_calls(expected_calls, any_order=False) - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_qgcs_2_4(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 2.0, 'PARAM1': 1.0} @@ -249,7 +252,7 @@ def test_output_params_qgcs_2_4(self, mock_print): unittest.mock.call("%u %u %-15s %.6f %u" % (2, 4, 'PARAM2', 2.0, 9))] mock_print.assert_has_calls(expected_calls, any_order=False) - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_qgcs_SYSID_THISMAV(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 2.0, 'PARAM1': 1.0, 'SYSID_THISMAV': 3.0} @@ -265,7 +268,7 @@ def test_output_params_qgcs_SYSID_THISMAV(self, mock_print): unittest.mock.call("%u %u %-15s %.6f %u" % (3, 7, 'SYSID_THISMAV', 3.0, 9))] mock_print.assert_has_calls(expected_calls, any_order=False) - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_qgcs_SYSID_INVALID(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 2.0, 'PARAM1': 1.0, 'SYSID_THISMAV': -1.0} @@ -282,7 +285,7 @@ def test_output_params_qgcs_SYSID_INVALID(self, mock_print): output_params(defaults, 'qgcs', MAVLINK_SYSID_MAX+2, 7) self.assertEqual(str(cm.exception), f"Invalid system ID parameter 16777218 must be smaller than {MAVLINK_SYSID_MAX}") - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_qgcs_COMPID_INVALID(self, mock_print): # Prepare a dummy defaults dictionary defaults = {'PARAM2': 2.0, 'PARAM1': 1.0} @@ -299,7 +302,7 @@ def test_output_params_qgcs_COMPID_INVALID(self, mock_print): output_params(defaults, 'qgcs', 1, MAVLINK_COMPID_MAX+3) self.assertEqual(str(cm.exception), f"Invalid component ID parameter 259 must be smaller than {MAVLINK_COMPID_MAX}") - @patch('extract_param_defaults.print') + @patch('builtins.print') def test_output_params_integer(self, mock_print): # Prepare a dummy defaults dictionary with an integer value defaults = {'PARAM1': 1.01, 'PARAM2': 2.00} @@ -313,5 +316,6 @@ def test_output_params_integer(self, mock_print): mock_print.assert_has_calls(expected_calls, any_order=False) + if __name__ == '__main__': unittest.main() diff --git a/unittests/extract_param_defaults_test.sh b/unittests/extract_param_defaults_test.sh old mode 100644 new mode 100755 index 330a777..4d5f4ae --- a/unittests/extract_param_defaults_test.sh +++ b/unittests/extract_param_defaults_test.sh @@ -1,3 +1,3 @@ -python3 -m coverage run -m unittest extract_param_defaults_unittest.py +PYTHONPATH=../MethodicConfigurator python3 -m coverage run -m unittest extract_param_defaults_test.py python3 -m coverage html firefox htmlcov/extract_param_defaults_py.html \ No newline at end of file diff --git a/unittests/frontend_tkinter_test.py b/unittests/frontend_tkinter_test.py old mode 100644 new mode 100755 index ef0c4f3..074143e --- a/unittests/frontend_tkinter_test.py +++ b/unittests/frontend_tkinter_test.py @@ -13,8 +13,8 @@ import unittest from unittest.mock import patch, MagicMock import tkinter as tk -from frontend_tkinter_base import show_error_message -from frontend_tkinter_base import show_tooltip +from MethodicConfigurator.frontend_tkinter_base import show_error_message +from MethodicConfigurator.frontend_tkinter_base import show_tooltip class TestShowErrorMessage(unittest.TestCase): @@ -77,10 +77,10 @@ def test_show_tooltip(self, mock_label, mock_toplevel): bg="#ffffe0", relief="solid", borderwidth=1, justify=tk.LEFT) # Assert that the Tkinter Toplevel instance's deiconify method was called - # mock_toplevel.return_value.deiconify.assert_called_once() + # mock_toplevel.return_value.deiconify.assert_called() # Assert that the Tkinter Toplevel instance's withdraw method was called - mock_toplevel.return_value.withdraw.assert_called_once() + mock_toplevel.return_value.withdraw.assert_called() # Assert that the Tkinter Label instance's pack method was called mock_label.return_value.pack.assert_called_once() diff --git a/unittests/param_pid_adjustment_update_test.py b/unittests/param_pid_adjustment_update_test.py old mode 100644 new mode 100755 index fcf1033..8bcec52 --- a/unittests/param_pid_adjustment_update_test.py +++ b/unittests/param_pid_adjustment_update_test.py @@ -20,9 +20,9 @@ import os import shutil -from param_pid_adjustment_update import ranged_type -from param_pid_adjustment_update import Par -from param_pid_adjustment_update import update_pid_adjustment_params +from MethodicConfigurator.param_pid_adjustment_update import ranged_type +from MethodicConfigurator.param_pid_adjustment_update import Par +from MethodicConfigurator.param_pid_adjustment_update import update_pid_adjustment_params class TestRangedType(unittest.TestCase): diff --git a/unittests/param_pid_adjustment_update_test.sh b/unittests/param_pid_adjustment_update_test.sh old mode 100644 new mode 100755 index 795fa8a..f5a1537 --- a/unittests/param_pid_adjustment_update_test.sh +++ b/unittests/param_pid_adjustment_update_test.sh @@ -1,3 +1,3 @@ -python3 -m coverage run -m unittest param_pid_adjustment_update_unittest.py +PYTHONPATH=../MethodicConfigurator python3 -m coverage run -m unittest param_pid_adjustment_update_test.py python3 -m coverage html firefox htmlcov/param_pid_adjustment_update_py.html \ No newline at end of file