From 2eb385c7747135b859c778f841fb89bbc4534232 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 13 Feb 2020 20:50:39 +0000 Subject: [PATCH 1/3] Migrate core and common --- .../openlp_core/common/test_mixins.py | 117 ++--- .../openlp_core/common/test_path.py | 373 +++++++-------- .../openlp_core/common/test_registry.py | 230 +++++----- .../openlp_core/common/test_settings.py | 423 +++++++++--------- tests/functional/openlp_core/test_server.py | 139 +++--- tests/functional/openlp_core/test_state.py | 172 ++++--- 6 files changed, 716 insertions(+), 738 deletions(-) diff --git a/tests/functional/openlp_core/common/test_mixins.py b/tests/functional/openlp_core/common/test_mixins.py index fa235653c..079670c0a 100644 --- a/tests/functional/openlp_core/common/test_mixins.py +++ b/tests/functional/openlp_core/common/test_mixins.py @@ -19,79 +19,82 @@ # along with this program. If not, see . # ########################################################################## """ -Package to test the openlp.core.common package. +Package to test the openlp.core.common.mixins package. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, patch from openlp.core.common.mixins import RegistryProperties from openlp.core.common.registry import Registry -class TestRegistryProperties(TestCase, RegistryProperties): +@pytest.fixture +def registry_env(): + """An instance of the Registry""" + Registry.create() + + class Test(RegistryProperties): + pass + return Test() + + +def test_no_application(registry_env): """ - Test the functions in the ThemeManager module + Test property if no registry value assigned """ - def setUp(self): - """ - Create the Register - """ - Registry.create() + # GIVEN an Empty Registry + # WHEN there is no Application + # THEN the application should be none + assert registry_env.application is None, 'The application value should be None' - def test_no_application(self): - """ - Test property if no registry value assigned - """ - # GIVEN an Empty Registry - # WHEN there is no Application - # THEN the application should be none - assert self.application is None, 'The application value should be None' - def test_application(self): - """ - Test property if registry value assigned - """ - # GIVEN an Empty Registry - application = MagicMock() +def test_application(registry_env): + """ + Test property if registry value assigned + """ + # GIVEN an Empty Registry + application = MagicMock() - # WHEN the application is registered - Registry().register('application', application) + # WHEN the application is registered + Registry().register('application', application) - # THEN the application should be none - assert self.application == application, 'The application value should match' + # THEN the application should be none + assert registry_env.application == application, 'The application value should match' - @patch('openlp.core.common.mixins.is_win') - def test_application_on_windows(self, mocked_is_win): - """ - Test property if registry value assigned on Windows - """ - # GIVEN an Empty Registry and we're on Windows - application = MagicMock() - mocked_is_win.return_value = True - # WHEN the application is registered - Registry().register('application', application) +@patch('openlp.core.common.mixins.is_win') +def test_application_on_windows(mocked_is_win, registry_env): + """ + Test property if registry value assigned on Windows + """ + # GIVEN an Empty Registry and we're on Windows + application = MagicMock() + mocked_is_win.return_value = True - # THEN the application should be none - assert self.application == application, 'The application value should match' + # WHEN the application is registered + Registry().register('application', application) - @patch('openlp.core.common.mixins.is_win') - def test_get_application_on_windows(self, mocked_is_win): - """ - Set that getting the application object on Windows happens dynamically - """ - # GIVEN an Empty Registry and we're on Windows - mocked_is_win.return_value = True - mock_application = MagicMock() - reg_props = RegistryProperties() - registry = Registry() + # THEN the application should be none + assert registry_env.application == application, 'The application value should match' - # WHEN the application is accessed - with patch.object(registry, 'get') as mocked_get: - mocked_get.return_value = mock_application - actual_application = reg_props.application - # THEN the application should be the mock object, and the correct function should have been called - assert mock_application == actual_application, 'The application value should match' - mocked_is_win.assert_called_with() - mocked_get.assert_called_with('application') +@patch('openlp.core.common.mixins.is_win') +def test_get_application_on_windows(mocked_is_win): + """ + Set that getting the application object on Windows happens dynamically + """ + # GIVEN an Empty Registry and we're on Windows + mocked_is_win.return_value = True + mock_application = MagicMock() + reg_props = RegistryProperties() + registry = Registry() + + # WHEN the application is accessed + with patch.object(registry, 'get') as mocked_get: + mocked_get.return_value = mock_application + actual_application = reg_props.application + + # THEN the application should be the mock object, and the correct function should have been called + assert mock_application == actual_application, 'The application value should match' + mocked_is_win.assert_called_with() + mocked_get.assert_called_with('application') diff --git a/tests/functional/openlp_core/common/test_path.py b/tests/functional/openlp_core/common/test_path.py index 2c0d1c162..3d654bfe9 100644 --- a/tests/functional/openlp_core/common/test_path.py +++ b/tests/functional/openlp_core/common/test_path.py @@ -22,218 +22,223 @@ Package to test the openlp.core.common.path package. """ import os +import pytest from pathlib import Path -from unittest import TestCase + from unittest.mock import MagicMock, patch from openlp.core.common.path import create_paths, files_to_paths, path_to_str, replace_params, str_to_path, which -class TestShutil(TestCase): +def test_replace_params_no_params(): """ - Tests for the :mod:`openlp.core.common.path` module + Test replace_params when called with and empty tuple instead of parameters to replace """ - def test_replace_params_no_params(self): - """ - Test replace_params when called with and empty tuple instead of parameters to replace - """ - # GIVEN: Some test data - test_args = (1, 2) - test_kwargs = {'arg3': 3, 'arg4': 4} - test_params = tuple() + # GIVEN: Some test data + test_args = (1, 2) + test_kwargs = {'arg3': 3, 'arg4': 4} + test_params = tuple() - # WHEN: Calling replace_params - result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) + # WHEN: Calling replace_params + result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) - # THEN: The positional and keyword args should not have changed - assert test_args == result_args - assert test_kwargs == result_kwargs - - def test_replace_params_params(self): - """ - Test replace_params when given a positional and a keyword argument to change - """ - # GIVEN: Some test data - test_args = (1, 2) - test_kwargs = {'arg3': 3, 'arg4': 4} - test_params = ((1, 'arg2', str), (2, 'arg3', str)) - - # WHEN: Calling replace_params - result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) - - # THEN: The positional and keyword args should have have changed - assert result_args == (1, '2') - assert result_kwargs == {'arg3': '3', 'arg4': 4} - - def test_which_no_command(self): - """ - Test :func:`openlp.core.common.path.which` when the command is not found. - """ - # GIVEN: A mocked :func:`shutil.which` when the command is not found. - with patch('openlp.core.common.path.shutil.which', return_value=None) as mocked_shutil_which: - - # WHEN: Calling :func:`openlp.core.common.path.which` with a command that does not exist. - result = which('no_command') - - # THEN: :func:`shutil.which` should have been called with the command, and :func:`which` should return None. - mocked_shutil_which.assert_called_once_with('no_command') - assert result is None - - def test_which_command(self): - """ - Test :func:`openlp.core.common.path.which` when a command has been found. - """ - # GIVEN: A mocked :func:`shutil.which` when the command is found. - with patch('openlp.core.common.path.shutil.which', - return_value=os.path.join('path', 'to', 'command')) as mocked_shutil_which: - - # WHEN: Calling :func:`openlp.core.common.path.which` with a command that exists. - result = which('command') - - # THEN: :func:`shutil.which` should have been called with the command, and :func:`which` should return a - # Path object equivalent of the command path. - mocked_shutil_which.assert_called_once_with('command') - assert result == Path('path', 'to', 'command') + # THEN: The positional and keyword args should not have changed + assert test_args == result_args + assert test_kwargs == result_kwargs -class TestPath(TestCase): +def test_replace_params_params(): """ - Tests for the :mod:`openlp.core.common.path` module + Test replace_params when given a positional and a keyword argument to change """ + # GIVEN: Some test data + test_args = (1, 2) + test_kwargs = {'arg3': 3, 'arg4': 4} + test_params = ((1, 'arg2', str), (2, 'arg3', str)) - def test_path_to_str_type_error(self): - """ - Test that `path_to_str` raises a type error when called with an invalid type - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling `path_to_str` with an invalid Type - # THEN: A TypeError should have been raised - with self.assertRaises(TypeError): - path_to_str(57) + # WHEN: Calling replace_params + result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) - def test_path_to_str_wth_str(self): - """ - Test that `path_to_str` just returns a str when given a str - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling `path_to_str` with a str - result = path_to_str('/usr/bin') + # THEN: The positional and keyword args should have have changed + assert result_args == (1, '2') + assert result_kwargs == {'arg3': '3', 'arg4': 4} - # THEN: The string should be returned - assert result == '/usr/bin' - def test_path_to_str_none(self): - """ - Test that `path_to_str` correctly converts the path parameter when passed with None - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling the `path_to_str` function with None - result = path_to_str(None) +def test_which_no_command(): + """ + Test :func:`openlp.core.common.path.which` when the command is not found. + """ + # GIVEN: A mocked :func:`shutil.which` when the command is not found. + with patch('openlp.core.common.path.shutil.which', return_value=None) as mocked_shutil_which: - # THEN: `path_to_str` should return an empty string - assert result == '' + # WHEN: Calling :func:`openlp.core.common.path.which` with a command that does not exist. + result = which('no_command') - def test_path_to_str_path_object(self): - """ - Test that `path_to_str` correctly converts the path parameter when passed a Path object - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling the `path_to_str` function with a Path object - result = path_to_str(Path('test/path')) + # THEN: :func:`shutil.which` should have been called with the command, and :func:`which` should return None. + mocked_shutil_which.assert_called_once_with('no_command') + assert result is None - # THEN: `path_to_str` should return a string representation of the Path object - assert result == os.path.join('test', 'path') - def test_str_to_path_type_error(self): - """ - Test that `str_to_path` returns None if called with invalid information - """ - # GIVEN: The `str_to_path` function - # WHEN: Calling `str_to_path` with an invalid Type - # THEN: None is returned - assert str_to_path(Path()) is None +def test_which_command(): + """ + Test :func:`openlp.core.common.path.which` when a command has been found. + """ + # GIVEN: A mocked :func:`shutil.which` when the command is found. + with patch('openlp.core.common.path.shutil.which', + return_value=os.path.join('path', 'to', 'command')) as mocked_shutil_which: - def test_str_to_path_empty_str(self): - """ - Test that `str_to_path` correctly converts the string parameter when passed with and empty string - """ - # GIVEN: The `str_to_path` function - # WHEN: Calling the `str_to_path` function with None - result = str_to_path('') + # WHEN: Calling :func:`openlp.core.common.path.which` with a command that exists. + result = which('command') - # THEN: `path_to_str` should return None - assert result is None + # THEN: :func:`shutil.which` should have been called with the command, and :func:`which` should return a + # Path object equivalent of the command path. + mocked_shutil_which.assert_called_once_with('command') + assert result == Path('path', 'to', 'command') - def test_create_paths_dir_exists(self): - """ - Test the create_paths() function when the path already exists - """ - # GIVEN: A `Path` to check with patched out mkdir and exists methods - mocked_path = MagicMock() - mocked_path.exists.return_value = True - # WHEN: `create_paths` is called and the path exists +def test_path_to_str_type_error(): + """ + Test that `path_to_str` raises a type error when called with an invalid type + """ + # GIVEN: The `path_to_str` function + # WHEN: Calling `path_to_str` with an invalid Type + # THEN: A TypeError should have been raised + with pytest.raises(TypeError): + path_to_str(57) + + +def test_path_to_str_wth_str(): + """ + Test that `path_to_str` just returns a str when given a str + """ + # GIVEN: The `path_to_str` function + # WHEN: Calling `path_to_str` with a str + result = path_to_str('/usr/bin') + + # THEN: The string should be returned + assert result == '/usr/bin' + + +def test_path_to_str_none(): + """ + Test that `path_to_str` correctly converts the path parameter when passed with None + """ + # GIVEN: The `path_to_str` function + # WHEN: Calling the `path_to_str` function with None + result = path_to_str(None) + + # THEN: `path_to_str` should return an empty string + assert result == '' + + +def test_path_to_str_path_object(): + """ + Test that `path_to_str` correctly converts the path parameter when passed a Path object + """ + # GIVEN: The `path_to_str` function + # WHEN: Calling the `path_to_str` function with a Path object + result = path_to_str(Path('test/path')) + + # THEN: `path_to_str` should return a string representation of the Path object + assert result == os.path.join('test', 'path') + + +def test_str_to_path_type_error(): + """ + Test that `str_to_path` returns None if called with invalid information + """ + # GIVEN: The `str_to_path` function + # WHEN: Calling `str_to_path` with an invalid Type + # THEN: None is returned + assert str_to_path(Path()) is None + + +def test_str_to_path_empty_str(): + """ + Test that `str_to_path` correctly converts the string parameter when passed with and empty string + """ + # GIVEN: The `str_to_path` function + # WHEN: Calling the `str_to_path` function with None + result = str_to_path('') + + # THEN: `path_to_str` should return None + assert result is None + + +def test_create_paths_dir_exists(): + """ + Test the create_paths() function when the path already exists + """ + # GIVEN: A `Path` to check with patched out mkdir and exists methods + mocked_path = MagicMock() + mocked_path.exists.return_value = True + + # WHEN: `create_paths` is called and the path exists + create_paths(mocked_path) + + # THEN: The function should not attempt to create the directory + mocked_path.exists.assert_called_once_with() + assert mocked_path.mkdir.call_count == 0, 'mkdir should not have been called' + + +def test_create_paths_dir_doesnt_exists(): + """ + Test the create_paths() function when the path does not already exist + """ + # GIVEN: A `Path` to check with patched out mkdir and exists methods + mocked_path = MagicMock() + mocked_path.exists.return_value = False + + # WHEN: `create_paths` is called and the path does not exist + create_paths(mocked_path) + + # THEN: The directory should have been created + mocked_path.exists.assert_called_once_with() + mocked_path.mkdir.assert_called_once_with(parents=True) + + +@patch('openlp.core.common.path.log') +def test_create_paths_dir_io_error(mocked_logger): + """ + Test the create_paths() when an OSError is raised + """ + # GIVEN: A `Path` to check with patched out mkdir and exists methods + mocked_path = MagicMock() + mocked_path.exists.side_effect = OSError('Cannot make directory') + + # WHEN: An OSError is raised when checking the if the path exists. + create_paths(mocked_path) + + # THEN: The Error should have been logged + mocked_logger.exception.assert_called_once_with('failed to check if directory exists or create directory') + + +def test_create_paths_dir_value_error(): + """ + Test the create_paths() when an error other than OSError is raised + """ + # GIVEN: A `Path` to check with patched out mkdir and exists methods + mocked_path = MagicMock() + mocked_path.exists.side_effect = ValueError('Some other error') + + # WHEN: Some other exception is raised + try: create_paths(mocked_path) + assert False, 'create_paths should have thrown an exception' + except Exception: + # THEN: `create_paths` raises an exception + pass - # THEN: The function should not attempt to create the directory - mocked_path.exists.assert_called_once_with() - assert mocked_path.mkdir.call_count == 0, 'mkdir should not have been called' - def test_create_paths_dir_doesnt_exists(self): - """ - Test the create_paths() function when the path does not already exist - """ - # GIVEN: A `Path` to check with patched out mkdir and exists methods - mocked_path = MagicMock() - mocked_path.exists.return_value = False +def test_files_to_paths(): + """ + Test the files_to_paths() method + """ + # GIVEN: A list of string filenames + test_files = ['/tmp/openlp/file1.txt', '/tmp/openlp/file2.txt'] - # WHEN: `create_paths` is called and the path does not exist - create_paths(mocked_path) + # WHEN: files_to_paths is called + result = files_to_paths(test_files) - # THEN: The directory should have been created - mocked_path.exists.assert_called_once_with() - mocked_path.mkdir.assert_called_once_with(parents=True) - - @patch('openlp.core.common.path.log') - def test_create_paths_dir_io_error(self, mocked_logger): - """ - Test the create_paths() when an OSError is raised - """ - # GIVEN: A `Path` to check with patched out mkdir and exists methods - mocked_path = MagicMock() - mocked_path.exists.side_effect = OSError('Cannot make directory') - - # WHEN: An OSError is raised when checking the if the path exists. - create_paths(mocked_path) - - # THEN: The Error should have been logged - mocked_logger.exception.assert_called_once_with('failed to check if directory exists or create directory') - - def test_create_paths_dir_value_error(self): - """ - Test the create_paths() when an error other than OSError is raised - """ - # GIVEN: A `Path` to check with patched out mkdir and exists methods - mocked_path = MagicMock() - mocked_path.exists.side_effect = ValueError('Some other error') - - # WHEN: Some other exception is raised - try: - create_paths(mocked_path) - assert False, 'create_paths should have thrown an exception' - except Exception: - # THEN: `create_paths` raises an exception - pass - - def test_files_to_paths(self): - """ - Test the files_to_paths() method - """ - # GIVEN: A list of string filenames - test_files = ['/tmp/openlp/file1.txt', '/tmp/openlp/file2.txt'] - - # WHEN: files_to_paths is called - result = files_to_paths(test_files) - - # THEN: The result should be a list of Paths - assert result == [Path('/tmp/openlp/file1.txt'), Path('/tmp/openlp/file2.txt')] + # THEN: The result should be a list of Paths + assert result == [Path('/tmp/openlp/file1.txt'), Path('/tmp/openlp/file2.txt')] diff --git a/tests/functional/openlp_core/common/test_registry.py b/tests/functional/openlp_core/common/test_registry.py index ed0833a51..d6f33aace 100644 --- a/tests/functional/openlp_core/common/test_registry.py +++ b/tests/functional/openlp_core/common/test_registry.py @@ -21,130 +21,127 @@ """ Package to test the openlp.core.lib package. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock from openlp.core.common.registry import Registry, RegistryBase -class TestRegistry(TestCase): +def dummy_function_1(): + return "function_1" - def test_registry_service(self): - """ - Test the registry creation and its usage - """ - # GIVEN: A new registry - Registry.create() - # WHEN: I add a component it should save it - mock_1 = MagicMock() +def dummy_function_2(): + return "function_2" + + +def test_registry_service(registry): + """ + Test the registry creation and its usage + """ + # GIVEN: A new registry + # WHEN: I add a component it should save it + mock_1 = MagicMock() + Registry().register('test1', mock_1) + + # THEN: we should be able retrieve the saved component + assert Registry().get('test1') == mock_1, 'The saved service can be retrieved and matches' + + # WHEN: I add a component for the second time I am mad. + # THEN and I will get an exception + with pytest.raises(KeyError) as context: Registry().register('test1', mock_1) + assert context.value != KeyError('Duplicate service exception test1'), \ + 'KeyError exception should have been thrown for duplicate service' - # THEN: we should be able retrieve the saved component - assert Registry().get('test1') == mock_1, 'The saved service can be retrieved and matches' + # WHEN I try to get back a non existent component + # THEN I will get an exception + temp = Registry().get('test2') + assert temp is None, 'None should have been returned for missing service' - # WHEN: I add a component for the second time I am mad. - # THEN and I will get an exception - with self.assertRaises(KeyError) as context: - Registry().register('test1', mock_1) - assert context.exception.args[0] == 'Duplicate service exception test1', \ - 'KeyError exception should have been thrown for duplicate service' + # WHEN I try to replace a component I should be allowed + Registry().remove('test1') + # THEN I will get an exception + temp = Registry().get('test1') + assert temp is None, 'None should have been returned for deleted service' - # WHEN I try to get back a non existent component - # THEN I will get an exception - temp = Registry().get('test2') - assert temp is None, 'None should have been returned for missing service' - # WHEN I try to replace a component I should be allowed - Registry().remove('test1') - # THEN I will get an exception - temp = Registry().get('test1') - assert temp is None, 'None should have been returned for deleted service' +def test_registry_function(registry): + """ + Test the registry function creation and their usages + """ + # GIVEN: An existing registry register a function + Registry().register_function('test1', dummy_function_1) - def test_registry_function(self): - """ - Test the registry function creation and their usages - """ - # GIVEN: An existing registry register a function - Registry.create() - Registry().register_function('test1', self.dummy_function_1) + # WHEN: I execute the function + return_value = Registry().execute('test1') - # WHEN: I execute the function - return_value = Registry().execute('test1') + # THEN: I expect then function to have been called and a return given + assert return_value[0] == 'function_1', 'A return value is provided and matches' - # THEN: I expect then function to have been called and a return given - assert return_value[0] == 'function_1', 'A return value is provided and matches' + # WHEN: I execute the a function with the same reference and execute the function + Registry().register_function('test1', dummy_function_1) + return_value = Registry().execute('test1') - # WHEN: I execute the a function with the same reference and execute the function - Registry().register_function('test1', self.dummy_function_1) - return_value = Registry().execute('test1') + # THEN: I expect then function to have been called and a return given + assert return_value == ['function_1', 'function_1'], 'A return value list is provided and matches' - # THEN: I expect then function to have been called and a return given - assert return_value == ['function_1', 'function_1'], 'A return value list is provided and matches' + # WHEN: I execute the a 2nd function with the different reference and execute the function + Registry().register_function('test2', dummy_function_2) + return_value = Registry().execute('test2') - # WHEN: I execute the a 2nd function with the different reference and execute the function - Registry().register_function('test2', self.dummy_function_2) - return_value = Registry().execute('test2') + # THEN: I expect then function to have been called and a return given + assert return_value[0] == 'function_2', 'A return value is provided and matches' - # THEN: I expect then function to have been called and a return given - assert return_value[0] == 'function_2', 'A return value is provided and matches' - def test_registry_working_flags(self): - """ - Test the registry working flags creation and its usage - """ - # GIVEN: A new registry - Registry.create() +def test_registry_working_flags(registry): + """ + Test the registry working flags creation and its usage + """ + # GIVEN: A new registry + # WHEN: I add a working flag it should save it + my_data = 'Lamas' + my_data2 = 'More Lamas' + Registry().set_flag('test1', my_data) - # WHEN: I add a working flag it should save it - my_data = 'Lamas' - my_data2 = 'More Lamas' - Registry().set_flag('test1', my_data) + # THEN: we should be able retrieve the saved component + temp = Registry().get_flag('test1') + assert temp == my_data, 'The value should have been saved' - # THEN: we should be able retrieve the saved component - temp = Registry().get_flag('test1') - assert temp == my_data, 'The value should have been saved' + # WHEN: I add a component for the second time I am not mad. + # THEN and I will not get an exception + Registry().set_flag('test1', my_data2) + temp = Registry().get_flag('test1') + assert temp == my_data2, 'The value should have been updated' - # WHEN: I add a component for the second time I am not mad. - # THEN and I will not get an exception - Registry().set_flag('test1', my_data2) - temp = Registry().get_flag('test1') - assert temp == my_data2, 'The value should have been updated' + # WHEN I try to get back a non existent Working Flag + # THEN I will get an exception + with pytest.raises(KeyError) as context1: + Registry().get_flag('test2') + assert context1.value != KeyError('Working Flag test2 not found in list'), \ + 'KeyError exception should have been thrown for missing working flag' - # WHEN I try to get back a non existent Working Flag - # THEN I will get an exception - with self.assertRaises(KeyError) as context1: - temp = Registry().get_flag('test2') - assert context1.exception.args[0] == 'Working Flag test2 not found in list', \ - 'KeyError exception should have been thrown for missing working flag' + # WHEN I try to replace a working flag I should be allowed + Registry().remove_flag('test1') + # THEN I will get an exception + with pytest.raises(KeyError) as context: + Registry().get_flag('test1') + assert context.value != 'Working Flag test1 not found in list', \ + 'KeyError exception should have been thrown for duplicate working flag' - # WHEN I try to replace a working flag I should be allowed - Registry().remove_flag('test1') - # THEN I will get an exception - with self.assertRaises(KeyError) as context: - temp = Registry().get_flag('test1') - assert context.exception.args[0] == 'Working Flag test1 not found in list', \ - 'KeyError exception should have been thrown for duplicate working flag' - def test_remove_function(self): - """ - Test the remove_function() method - """ - # GIVEN: An existing registry register a function - Registry.create() - Registry().register_function('test1', self.dummy_function_1) +def test_remove_function(registry): + """ + Test the remove_function() method + """ + # GIVEN: An existing registry register a function + Registry().register_function('test1', dummy_function_1) - # WHEN: Remove the function. - Registry().remove_function('test1', self.dummy_function_1) + # WHEN: Remove the function. + Registry().remove_function('test1', dummy_function_1) - # THEN: The method should not be available. - assert Registry().functions_list['test1'] == [], 'The function should not be in the dict anymore.' - - def dummy_function_1(self): - return "function_1" - - def dummy_function_2(self): - return "function_2" + # THEN: The method should not be available. + assert Registry().functions_list['test1'] == [], 'The function should not be in the dict anymore.' class PlainStub(object): @@ -157,30 +154,25 @@ class RegistryStub(RegistryBase): super().__init__() -class TestRegistryBase(TestCase): +def test_registry_mixin_missing(registry): + """ + Test the registry creation and its usage + """ + # GIVEN: A new registry + # WHEN: I create an instance of a class that doesn't inherit from RegistryMixin + PlainStub() - def test_registry_mixin_missing(self): - """ - Test the registry creation and its usage - """ - # GIVEN: A new registry - Registry.create() + # THEN: Nothing is registered with the registry + assert len(Registry().functions_list) == 0, 'The function should not be in the dict anymore.' - # WHEN: I create an instance of a class that doesn't inherit from RegistryMixin - PlainStub() - # THEN: Nothing is registered with the registry - assert len(Registry().functions_list) == 0, 'The function should not be in the dict anymore.' +def test_registry_mixin_present(registry): + """ + Test the registry creation and its usage + """ + # GIVEN: A new registry + # WHEN: I create an instance of a class that inherits from RegistryMixin + RegistryStub() - def test_registry_mixin_present(self): - """ - Test the registry creation and its usage - """ - # GIVEN: A new registry - Registry.create() - - # WHEN: I create an instance of a class that inherits from RegistryMixin - RegistryStub() - - # THEN: The bootstrap methods should be registered - assert len(Registry().functions_list) == 3, 'The bootstrap functions should be in the dict.' + # THEN: The bootstrap methods should be registered + assert len(Registry().functions_list) == 3, 'The bootstrap functions should be in the dict.' diff --git a/tests/functional/openlp_core/common/test_settings.py b/tests/functional/openlp_core/common/test_settings.py index a2a97ca73..fe13ad29c 100644 --- a/tests/functional/openlp_core/common/test_settings.py +++ b/tests/functional/openlp_core/common/test_settings.py @@ -21,272 +21,271 @@ """ Package to test the openlp.core.lib.settings package. """ +import pytest from pathlib import Path -from unittest import TestCase from unittest.mock import call, patch from openlp.core.common import settings from openlp.core.common.settings import Settings, media_players_conv -from tests.helpers.testmixin import TestMixin -class TestSettings(TestCase, TestMixin): - """ - Test the functions in the Settings module - """ - def setUp(self): - """ - Create the UI - """ - self.setup_application() - self.build_settings() +def test_media_players_conv(): + """Test the media players conversion function""" + # GIVEN: A list of media players + media_players = 'phonon,webkit,vlc' - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - self.destroy_settings() + # WHEN: The media converter function is called + result = media_players_conv(media_players) - def test_media_players_conv(self): - """Test the media players conversion function""" - # GIVEN: A list of media players - media_players = 'phonon,webkit,vlc' + # THEN: The list should have been converted correctly + assert result == 'system,webkit,vlc' - # WHEN: The media converter function is called - result = media_players_conv(media_players) - # THEN: The list should have been converted correctly - assert result == 'system,webkit,vlc' +def test_default_value(settings): + """Test reading a setting that doesn't exist yet""" + # GIVEN: A setting that doesn't exist yet - def test_default_value(self): - """Test reading a setting that doesn't exist yet""" - # GIVEN: A setting that doesn't exist yet + # WHEN reading a setting for the first time + default_value = Settings().value('core/has run wizard') - # WHEN reading a setting for the first time - default_value = Settings().value('core/has run wizard') + # THEN the default value is returned + assert default_value is False, 'The default value should be False' - # THEN the default value is returned - assert default_value is False, 'The default value should be False' - def test_save_new_value(self): - """Test saving a new setting""" - # GIVEN: A setting that hasn't been saved yet - # WHEN a new value is saved into config - Settings().setValue('core/has run wizard', True) +def test_save_new_value(settings): + """Test saving a new setting""" + # GIVEN: A setting that hasn't been saved yet + # WHEN a new value is saved into config + Settings().setValue('core/has run wizard', True) - # THEN the new value is returned when re-read - assert Settings().value('core/has run wizard') is True, 'The saved value should have been returned' + # THEN the new value is returned when re-read + assert Settings().value('core/has run wizard') is True, 'The saved value should have been returned' - def test_set_up_default_values(self): - """Test that the default values are updated""" - # GIVEN: A Settings object with defaults - # WHEN: set_up_default_values() is called - Settings.set_up_default_values() - # THEN: The default values should have been added to the dictionary - assert 'advanced/default service name' in Settings.__default_settings__ +def test_set_up_default_values(): + """Test that the default values are updated""" + # GIVEN: A Settings object with defaults + # WHEN: set_up_default_values() is called + Settings.set_up_default_values() - def test_get_default_value(self): - """Test that the default value for a setting is returned""" - # GIVEN: A Settings class with a default value - Settings.__default_settings__['test/moo'] = 'baa' + # THEN: The default values should have been added to the dictionary + assert 'advanced/default service name' in Settings.__default_settings__ - # WHEN: get_default_value() is called - result = Settings().get_default_value('test/moo') - # THEN: The correct default value should be returned - assert result == 'baa' +def test_get_default_value(): + """Test that the default value for a setting is returned""" + # GIVEN: A Settings class with a default value + Settings.__default_settings__['test/moo'] = 'baa' - def test_settings_override(self): - """Test the Settings creation and its override usage""" - # GIVEN: an override for the settings - screen_settings = { - 'test/extend': 'very wide', - } - Settings().extend_default_settings(screen_settings) + # WHEN: get_default_value() is called + result = Settings().get_default_value('test/moo') - # WHEN reading a setting for the first time - extend = Settings().value('test/extend') + # THEN: The correct default value should be returned + assert result == 'baa' - # THEN the default value is returned - assert extend == 'very wide', 'The default value of "very wide" should be returned' - def test_save_existing_setting(self): - """Test that saving an existing setting returns the new value""" - # GIVEN: An existing setting - Settings().extend_default_settings({'test/existing value': None}) - Settings().setValue('test/existing value', 'old value') +def test_settings_override(): + """Test the Settings creation and its override usage""" + # GIVEN: an override for the settings + screen_settings = { + 'test/extend': 'very wide', + } + Settings().extend_default_settings(screen_settings) - # WHEN a new value is saved into config - Settings().setValue('test/existing value', 'new value') + # WHEN reading a setting for the first time + extend = Settings().value('test/extend') - # THEN the new value is returned when re-read - assert Settings().value('test/existing value') == 'new value', 'The saved value should be returned' + # THEN the default value is returned + assert extend == 'very wide', 'The default value of "very wide" should be returned' - def test_settings_override_with_group(self): - """Test the Settings creation and its override usage - with groups""" - # GIVEN: an override for the settings - screen_settings = { - 'test/extend': 'very wide', - } - Settings.extend_default_settings(screen_settings) - # WHEN reading a setting for the first time - settings = Settings() - settings.beginGroup('test') - extend = settings.value('extend') +def test_save_existing_setting(): + """Test that saving an existing setting returns the new value""" + # GIVEN: An existing setting + Settings().extend_default_settings({'test/existing value': None}) + Settings().setValue('test/existing value', 'old value') - # THEN the default value is returned - assert 'very wide' == extend, 'The default value defined should be returned' + # WHEN a new value is saved into config + Settings().setValue('test/existing value', 'new value') - # WHEN a new value is saved into config - Settings().setValue('test/extend', 'very short') + # THEN the new value is returned when re-read + assert Settings().value('test/existing value') == 'new value', 'The saved value should be returned' - # THEN the new value is returned when re-read - assert 'very short' == Settings().value('test/extend'), 'The saved value should be returned' - def test_settings_nonexisting(self): - """Test the Settings on query for non-existing value""" - # GIVEN: A new Settings setup - with self.assertRaises(KeyError) as cm: - # WHEN reading a setting that doesn't exists - Settings().value('core/does not exists') +def test_settings_override_with_group(): + """Test the Settings creation and its override usage - with groups""" + # GIVEN: an override for the settings + screen_settings = { + 'test/extend': 'very wide', + } + Settings.extend_default_settings(screen_settings) - # THEN: An exception with the non-existing key should be thrown - assert str(cm.exception) == "'core/does not exists'", 'We should get an exception' + # WHEN reading a setting for the first time + settings = Settings() + settings.beginGroup('test') + extend = settings.value('extend') - def test_extend_default_settings(self): - """Test that the extend_default_settings method extends the default settings""" - # GIVEN: A patched __default_settings__ dictionary - with patch.dict(Settings.__default_settings__, - {'test/setting 1': 1, 'test/setting 2': 2, 'test/setting 3': 3}, True): + # THEN the default value is returned + assert 'very wide' == extend, 'The default value defined should be returned' - # WHEN: Calling extend_default_settings - Settings.extend_default_settings({'test/setting 3': 4, 'test/extended 1': 1, 'test/extended 2': 2}) + # WHEN a new value is saved into config + Settings().setValue('test/extend', 'very short') - # THEN: The _default_settings__ dictionary_ should have the new keys - assert Settings.__default_settings__ == {'test/setting 1': 1, 'test/setting 2': 2, 'test/setting 3': 4, - 'test/extended 1': 1, 'test/extended 2': 2} + # THEN the new value is returned when re-read + assert 'very short' == Settings().value('test/extend'), 'The saved value should be returned' - @patch('openlp.core.common.settings.QtCore.QSettings.contains') - @patch('openlp.core.common.settings.QtCore.QSettings.value') - @patch('openlp.core.common.settings.QtCore.QSettings.setValue') - @patch('openlp.core.common.settings.QtCore.QSettings.remove') - def test_upgrade_single_setting(self, mocked_remove, mocked_setValue, mocked_value, mocked_contains): - """Test that the upgrade mechanism for settings works correctly for single value upgrades""" - # GIVEN: A settings object with an upgrade step to take (99, so that we don't interfere with real ones) - local_settings = Settings() - local_settings.__setting_upgrade_99__ = [ - ('single/value', 'single/new value', [(str, '')]) - ] - settings.__version__ = 99 - mocked_value.side_effect = [98, 10] - mocked_contains.return_value = True - # WHEN: upgrade_settings() is called - local_settings.upgrade_settings() +def test_settings_nonexisting(): + """Test the Settings on query for non-existing value""" + # GIVEN: A new Settings setup + with pytest.raises(KeyError) as cm: + # WHEN reading a setting that doesn't exists + Settings().value('core/does not exists') - # THEN: The correct calls should have been made with the correct values - assert mocked_value.call_count == 2, 'Settings().value() should have been called twice' - assert mocked_value.call_args_list == [call('settings/version', 0), call('single/value')] - assert mocked_setValue.call_count == 2, 'Settings().setValue() should have been called twice' - assert mocked_setValue.call_args_list == [call('single/new value', '10'), call('settings/version', 99)] - mocked_contains.assert_called_once_with('single/value') - mocked_remove.assert_called_once_with('single/value') + # THEN: An exception with the non-existing key should be thrown + assert str(cm.value) != KeyError("'core/does not exists'", 'We should get an exception') - @patch('openlp.core.common.settings.QtCore.QSettings.contains') - @patch('openlp.core.common.settings.QtCore.QSettings.value') - @patch('openlp.core.common.settings.QtCore.QSettings.setValue') - @patch('openlp.core.common.settings.QtCore.QSettings.remove') - def test_upgrade_setting_value(self, mocked_remove, mocked_setValue, mocked_value, mocked_contains): - """Test that the upgrade mechanism for settings correctly uses the new value when it's not a function""" - # GIVEN: A settings object with an upgrade step to take (99, so that we don't interfere with real ones) - local_settings = Settings() - local_settings.__setting_upgrade_99__ = [ - ('values/old value', 'values/new value', [(True, 1)]) - ] - settings.__version__ = 99 - mocked_value.side_effect = [98, 1] - mocked_contains.return_value = True - # WHEN: upgrade_settings() is called - local_settings.upgrade_settings() +def test_extend_default_settings(): + """Test that the extend_default_settings method extends the default settings""" + # GIVEN: A patched __default_settings__ dictionary + with patch.dict(Settings.__default_settings__, + {'test/setting 1': 1, 'test/setting 2': 2, 'test/setting 3': 3}, True): - # THEN: The correct calls should have been made with the correct values - assert mocked_value.call_count == 2, 'Settings().value() should have been called twice' - assert mocked_value.call_args_list == [call('settings/version', 0), call('values/old value')] - assert mocked_setValue.call_count == 2, 'Settings().setValue() should have been called twice' - assert mocked_setValue.call_args_list == [call('values/new value', True), call('settings/version', 99)] - mocked_contains.assert_called_once_with('values/old value') - mocked_remove.assert_called_once_with('values/old value') + # WHEN: Calling extend_default_settings + Settings.extend_default_settings({'test/setting 3': 4, 'test/extended 1': 1, 'test/extended 2': 2}) - @patch('openlp.core.common.settings.QtCore.QSettings.contains') - @patch('openlp.core.common.settings.QtCore.QSettings.value') - @patch('openlp.core.common.settings.QtCore.QSettings.setValue') - @patch('openlp.core.common.settings.QtCore.QSettings.remove') - def test_upgrade_multiple_one_invalid(self, mocked_remove, mocked_setValue, mocked_value, mocked_contains): - """Test that the upgrade mechanism for settings works correctly for multiple values where one is invalid""" - # GIVEN: A settings object with an upgrade step to take - local_settings = Settings() - local_settings.__setting_upgrade_99__ = [ - (['multiple/value 1', 'multiple/value 2'], 'single/new value', []) - ] - settings.__version__ = 99 - mocked_value.side_effect = [98, 10] - mocked_contains.side_effect = [True, False] + # THEN: The _default_settings__ dictionary_ should have the new keys + assert Settings.__default_settings__ == {'test/setting 1': 1, 'test/setting 2': 2, 'test/setting 3': 4, + 'test/extended 1': 1, 'test/extended 2': 2} - # WHEN: upgrade_settings() is called - local_settings.upgrade_settings() - # THEN: The correct calls should have been made with the correct values - mocked_value.assert_called_once_with('settings/version', 0) - mocked_setValue.assert_called_once_with('settings/version', 99) - assert mocked_contains.call_args_list == [call('multiple/value 1'), call('multiple/value 2')] +@patch('openlp.core.common.settings.QtCore.QSettings.contains') +@patch('openlp.core.common.settings.QtCore.QSettings.value') +@patch('openlp.core.common.settings.QtCore.QSettings.setValue') +@patch('openlp.core.common.settings.QtCore.QSettings.remove') +def test_upgrade_single_setting(mocked_remove, mocked_setValue, mocked_value, mocked_contains): + """Test that the upgrade mechanism for settings works correctly for single value upgrades""" + # GIVEN: A settings object with an upgrade step to take (99, so that we don't interfere with real ones) + local_settings = Settings() + local_settings.__setting_upgrade_99__ = [ + ('single/value', 'single/new value', [(str, '')]) + ] + settings.__version__ = 99 + mocked_value.side_effect = [98, 10] + mocked_contains.return_value = True - def test_can_upgrade(self): - """Test the Settings.can_upgrade() method""" - # GIVEN: A Settings object - local_settings = Settings() + # WHEN: upgrade_settings() is called + local_settings.upgrade_settings() - # WHEN: can_upgrade() is run - result = local_settings.can_upgrade() + # THEN: The correct calls should have been made with the correct values + assert mocked_value.call_count == 2, 'Settings().value() should have been called twice' + assert mocked_value.call_args_list == [call('settings/version', 0), call('single/value')] + assert mocked_setValue.call_count == 2, 'Settings().setValue() should have been called twice' + assert mocked_setValue.call_args_list == [call('single/new value', '10'), call('settings/version', 99)] + mocked_contains.assert_called_once_with('single/value') + mocked_remove.assert_called_once_with('single/value') - # THEN: The result should be True - assert result is True, 'The settings should be upgradeable' - def test_convert_value_setting_none_str(self): - """Test the Settings._convert_value() method when a setting is None and the default value is a string""" - # GIVEN: A settings object - # WHEN: _convert_value() is run - result = Settings()._convert_value(None, 'string') +@patch('openlp.core.common.settings.QtCore.QSettings.contains') +@patch('openlp.core.common.settings.QtCore.QSettings.value') +@patch('openlp.core.common.settings.QtCore.QSettings.setValue') +@patch('openlp.core.common.settings.QtCore.QSettings.remove') +def test_upgrade_setting_value(mocked_remove, mocked_setValue, mocked_value, mocked_contains): + """Test that the upgrade mechanism for settings correctly uses the new value when it's not a function""" + # GIVEN: A settings object with an upgrade step to take (99, so that we don't interfere with real ones) + local_settings = Settings() + local_settings.__setting_upgrade_99__ = [ + ('values/old value', 'values/new value', [(True, 1)]) + ] + settings.__version__ = 99 + mocked_value.side_effect = [98, 1] + mocked_contains.return_value = True - # THEN: The result should be an empty string - assert result == '', 'The result should be an empty string' + # WHEN: upgrade_settings() is called + local_settings.upgrade_settings() - def test_convert_value_setting_none_list(self): - """Test the Settings._convert_value() method when a setting is None and the default value is a list""" - # GIVEN: A settings object - # WHEN: _convert_value() is run - result = Settings()._convert_value(None, [None]) + # THEN: The correct calls should have been made with the correct values + assert mocked_value.call_count == 2, 'Settings().value() should have been called twice' + assert mocked_value.call_args_list == [call('settings/version', 0), call('values/old value')] + assert mocked_setValue.call_count == 2, 'Settings().setValue() should have been called twice' + assert mocked_setValue.call_args_list == [call('values/new value', True), call('settings/version', 99)] + mocked_contains.assert_called_once_with('values/old value') + mocked_remove.assert_called_once_with('values/old value') - # THEN: The result should be an empty list - assert result == [], 'The result should be an empty list' - def test_convert_value_setting_json_Path(self): - """Test the Settings._convert_value() method when a setting is JSON and represents a Path object""" - # GIVEN: A settings object - # WHEN: _convert_value() is run - result = Settings()._convert_value( - '{"parts": ["openlp", "core"], "json_meta": {"class": "Path", "version": 1}}', None) +@patch('openlp.core.common.settings.QtCore.QSettings.contains') +@patch('openlp.core.common.settings.QtCore.QSettings.value') +@patch('openlp.core.common.settings.QtCore.QSettings.setValue') +@patch('openlp.core.common.settings.QtCore.QSettings.remove') +def test_upgrade_multiple_one_invalid(mocked_remove, mocked_setValue, mocked_value, mocked_contains): + """Test that the upgrade mechanism for settings works correctly for multiple values where one is invalid""" + # GIVEN: A settings object with an upgrade step to take + local_settings = Settings() + local_settings.__setting_upgrade_99__ = [ + (['multiple/value 1', 'multiple/value 2'], 'single/new value', []) + ] + settings.__version__ = 99 + mocked_value.side_effect = [98, 10] + mocked_contains.side_effect = [True, False] - # THEN: The result should be a Path object - assert isinstance(result, Path), 'The result should be a Path object' + # WHEN: upgrade_settings() is called + local_settings.upgrade_settings() - def test_convert_value_setting_bool_str(self): - """Test the Settings._convert_value() method when a setting is supposed to be a boolean""" - # GIVEN: A settings object - # WHEN: _convert_value() is run - result = Settings()._convert_value('false', True) + # THEN: The correct calls should have been made with the correct values + mocked_value.assert_called_once_with('settings/version', 0) + mocked_setValue.assert_called_once_with('settings/version', 99) + assert mocked_contains.call_args_list == [call('multiple/value 1'), call('multiple/value 2')] - # THEN: The result should be False - assert result is False, 'The result should be False' + +def test_can_upgrade(): + """Test the Settings.can_upgrade() method""" + # GIVEN: A Settings object + local_settings = Settings() + + # WHEN: can_upgrade() is run + result = local_settings.can_upgrade() + + # THEN: The result should be True + assert result is True, 'The settings should be upgradeable' + + +def test_convert_value_setting_none_str(): + """Test the Settings._convert_value() method when a setting is None and the default value is a string""" + # GIVEN: A settings object + # WHEN: _convert_value() is run + result = Settings()._convert_value(None, 'string') + + # THEN: The result should be an empty string + assert result == '', 'The result should be an empty string' + + +def test_convert_value_setting_none_list(): + """Test the Settings._convert_value() method when a setting is None and the default value is a list""" + # GIVEN: A settings object + # WHEN: _convert_value() is run + result = Settings()._convert_value(None, [None]) + + # THEN: The result should be an empty list + assert result == [], 'The result should be an empty list' + + +def test_convert_value_setting_json_Path(): + """Test the Settings._convert_value() method when a setting is JSON and represents a Path object""" + # GIVEN: A settings object + # WHEN: _convert_value() is run + result = Settings()._convert_value( + '{"parts": ["openlp", "core"], "json_meta": {"class": "Path", "version": 1}}', None) + + # THEN: The result should be a Path object + assert isinstance(result, Path), 'The result should be a Path object' + + +def test_convert_value_setting_bool_str(): + """Test the Settings._convert_value() method when a setting is supposed to be a boolean""" + # GIVEN: A settings object + # WHEN: _convert_value() is run + result = Settings()._convert_value('false', True) + + # THEN: The result should be False + assert result is False, 'The result should be False' diff --git a/tests/functional/openlp_core/test_server.py b/tests/functional/openlp_core/test_server.py index d2e709a0c..f56704598 100644 --- a/tests/functional/openlp_core/test_server.py +++ b/tests/functional/openlp_core/test_server.py @@ -18,96 +18,95 @@ # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # ########################################################################## +import pytest from pathlib import Path -from unittest import TestCase from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry from openlp.core.server import Server -from tests.helpers.testmixin import TestMixin -class TestServer(TestCase, TestMixin): +@pytest.fixture +def server(registry): + with patch('PyQt5.QtNetwork.QLocalSocket'): + server = Server() + yield server + server.close_server() + + +def test_is_another_instance_running(server): """ - Test the Server Class used to check if OpenLP is running. + Run a test as if this was the first time and no instance is running """ - def setUp(self): - Registry.create() - with patch('PyQt5.QtNetwork.QLocalSocket'): - self.server = Server() + # GIVEN: A running Server - def tearDown(self): - self.server.close_server() + # WHEN: I ask for it to start + value = server.is_another_instance_running() - def test_is_another_instance_running(self): - """ - Run a test as if this was the first time and no instance is running - """ - # GIVEN: A running Server + # THEN the following is called + server.out_socket.waitForConnected.assert_called_once_with() + server.out_socket.connectToServer.assert_called_once_with(server.id) + assert isinstance(value, MagicMock) - # WHEN: I ask for it to start - value = self.server.is_another_instance_running() - # THEN the following is called - self.server.out_socket.waitForConnected.assert_called_once_with() - self.server.out_socket.connectToServer.assert_called_once_with(self.server.id) - assert isinstance(value, MagicMock) +def test_is_another_instance_running_true(server): + """ + Run a test as if there is another instance running + """ + # GIVEN: A running Server + server.out_socket.waitForConnected.return_value = True - def test_is_another_instance_running_true(self): - """ - Run a test as if there is another instance running - """ - # GIVEN: A running Server - self.server.out_socket.waitForConnected.return_value = True + # WHEN: I ask for it to start + value = server.is_another_instance_running() - # WHEN: I ask for it to start - value = self.server.is_another_instance_running() + # THEN the following is called + server.out_socket.waitForConnected.assert_called_once_with() + server.out_socket.connectToServer.assert_called_once_with(server.id) + assert value is True - # THEN the following is called - self.server.out_socket.waitForConnected.assert_called_once_with() - self.server.out_socket.connectToServer.assert_called_once_with(self.server.id) - assert value is True - def test_on_read_ready(self): - """ - Test the on_read_ready method calls the service_manager - """ - # GIVEN: A server with a service manager - self.server.in_stream = MagicMock() - service_manager = MagicMock() - Registry().register('service_manager', service_manager) +def test_on_read_ready(server): + """ + Test the on_read_ready method calls the service_manager + """ + # GIVEN: A server with a service manager + server.in_stream = MagicMock() + service_manager = MagicMock() + Registry().register('service_manager', service_manager) - # WHEN: a file is added to the socket and the method called - file_name = '\\home\\superfly\\' - self.server.in_stream.readLine.return_value = file_name - self.server._on_ready_read() + # WHEN: a file is added to the socket and the method called + file_name = '\\home\\superfly\\' + server.in_stream.readLine.return_value = file_name + server._on_ready_read() - # THEN: the service will be loaded - assert service_manager.load_service.call_count == 1 - service_manager.load_service.assert_called_once_with(Path(file_name)) + # THEN: the service will be loaded + assert service_manager.load_service.call_count == 1 + service_manager.load_service.assert_called_once_with(Path(file_name)) - @patch("PyQt5.QtCore.QTextStream") - def test_post_to_server(self, mocked_stream): - """ - A Basic test with a post to the service - :return: - """ - # GIVEN: A server - # WHEN: I post to a server - self.server.post_to_server(['l', 'a', 'm', 'a', 's']) - # THEN: the file should be passed out to the socket - self.server.out_socket.write.assert_called_once_with(b'lamas') +@patch("PyQt5.QtCore.QTextStream") +def test_post_to_server(mocked_stream, server): + """ + A Basic test with a post to the service + :return: + """ + # GIVEN: A server + # WHEN: I post to a server + server.post_to_server(['l', 'a', 'm', 'a', 's']) - @patch("PyQt5.QtCore.QTextStream") - def test_post_to_server_openlp(self, mocked_stream): - """ - A Basic test with a post to the service with OpenLP - :return: - """ - # GIVEN: A server - # WHEN: I post to a server - self.server.post_to_server(['l', 'a', 'm', 'a', 's', 'OpenLP']) + # THEN: the file should be passed out to the socket + server.out_socket.write.assert_called_once_with(b'lamas') - # THEN: the file should be passed out to the socket - self.server.out_socket.write.assert_called_once_with(b'lamas') + +@patch("PyQt5.QtCore.QTextStream") +def test_post_to_server_openlp(mocked_stream, server): + """ + A Basic test with a post to the service with OpenLP + :return: + """ + # GIVEN: A server + # WHEN: I post to a server + server.post_to_server(['l', 'a', 'm', 'a', 's', 'OpenLP']) + + # THEN: the file should be passed out to the socket + server.out_socket.write.assert_called_once_with(b'lamas') diff --git a/tests/functional/openlp_core/test_state.py b/tests/functional/openlp_core/test_state.py index a20cb8e13..6518cef8a 100644 --- a/tests/functional/openlp_core/test_state.py +++ b/tests/functional/openlp_core/test_state.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - ########################################################################## # OpenLP - Open Source Lyrics Projection # # ---------------------------------------------------------------------- # @@ -18,133 +17,114 @@ # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # ########################################################################## -from unittest import TestCase from unittest.mock import MagicMock from openlp.core.state import State from openlp.core.common.registry import Registry from openlp.core.lib.plugin import PluginStatus -from tests.helpers.testmixin import TestMixin """ -Test the Status class. +Test the States class. """ -class TestState(TestCase, TestMixin): - """ - Test the Server Class used to check if OpenLP is running. - """ - def setUp(self): - Registry.create() +def test_add_service(state): + # GIVEN a new state + # WHEN I add a new service + State().add_service("test", 1, PluginStatus.Active) - def tearDown(self): - pass + # THEN I have a saved service + assert len(State().modules) == 1 - def test_add_service(self): - # GIVEN a new state - State().load_settings() - # WHEN I add a new service - State().add_service("test", 1, PluginStatus.Active) +def test_add_service_multiple(state): + # GIVEN a new state + # WHEN I add a new service twice + State().add_service("test", 1, PluginStatus.Active) + State().add_service("test", 1, PluginStatus.Active) - # THEN I have a saved service - assert len(State().modules) == 1 + # THEN I have a single saved service + assert len(State().modules) == 1 - def test_add_service_multiple(self): - # GIVEN a new state - State().load_settings() - # WHEN I add a new service twice - State().add_service("test", 1, PluginStatus.Active) - State().add_service("test", 1, PluginStatus.Active) +def test_add_service_multiple_depend(state): + # GIVEN a new state + # WHEN I add a new service twice + State().add_service("test", 1, 1, PluginStatus.Active) + State().add_service("test1", 1, 1, PluginStatus.Active, "test") + State().add_service("test1", 1, 1, PluginStatus.Active, "test") - # THEN I have a single saved service - assert len(State().modules) == 1 + # THEN I have still have a single saved service and one dependency + assert len(State().modules) == 2 + assert len(State().modules['test'].required_by) == 1 - def test_add_service_multiple_depend(self): - # GIVEN a new state - State().load_settings() - # WHEN I add a new service twice - State().add_service("test", 1, 1, PluginStatus.Active) - State().add_service("test1", 1, 1, PluginStatus.Active, "test") - State().add_service("test1", 1, 1, PluginStatus.Active, "test") +def test_add_service_multiple_depends(state): + # GIVEN a new state + # WHEN I add a new service twice + State().add_service("test", 1, 1, PluginStatus.Active) + State().add_service("test1", 1, 1, PluginStatus.Active, "test") + State().add_service("test2", 1, 1, PluginStatus.Active, "test") - # THEN I have still have a single saved service and one dependency - assert len(State().modules) == 2 - assert len(State().modules['test'].required_by) == 1 + # THEN I have a 3 modules and 2 dependencies + assert len(State().modules) == 3 + assert len(State().modules['test'].required_by) == 2 - def test_add_service_multiple_depends(self): - # GIVEN a new state - State().load_settings() - # WHEN I add a new service twice - State().add_service("test", 1, 1, PluginStatus.Active) - State().add_service("test1", 1, 1, PluginStatus.Active, "test") - State().add_service("test2", 1, 1, PluginStatus.Active, "test") +def test_active_service(state): + # GIVEN a new state + # WHEN I add a new service which is Active + State().add_service("test", 1, 1, PluginStatus.Active) - # THEN I have a 3 modules and 2 dependencies - assert len(State().modules) == 3 - assert len(State().modules['test'].required_by) == 2 + # THEN I have a single saved service + assert State().is_module_active('test') is True - def test_active_service(self): - # GIVEN a new state - State().load_settings() - # WHEN I add a new service which is Active - State().add_service("test", 1, 1, PluginStatus.Active) +def test_inactive_service(state): + # GIVEN a new state + # WHEN I add a new service which is Inactive + State().add_service("test", 1, 1, PluginStatus.Inactive) - # THEN I have a single saved service - assert State().is_module_active('test') is True + # THEN I have a single saved service + assert State().is_module_active('test') is False - def test_inactive_service(self): - # GIVEN a new state - State().load_settings() - # WHEN I add a new service which is Inactive - State().add_service("test", 1, 1, PluginStatus.Inactive) +def test_basic_preconditions_fail(state, registry): + # GIVEN a new state + Registry().register('test_plugin', MagicMock()) - # THEN I have a single saved service - assert State().is_module_active('test') is False + # WHEN I add a new services with dependencies and a failed pre condition + State().add_service("test", 1, 1, PluginStatus.Inactive) + State().add_service("test2", 1, 1, PluginStatus.Inactive) + State().add_service("test1", 1, 1, PluginStatus.Inactive, 'test') + State().update_pre_conditions('test', False) - def test_basic_preconditions_fail(self): - # GIVEN a new state - State().load_settings() - Registry().register('test_plugin', MagicMock()) + # THEN correct the state when I flush the preconditions + assert State().modules['test'].pass_preconditions is False + assert State().modules['test2'].pass_preconditions is False + assert State().modules['test1'].pass_preconditions is False + State().flush_preconditions() + assert State().modules['test'].pass_preconditions is False + assert State().modules['test2'].pass_preconditions is False + assert State().modules['test1'].pass_preconditions is False - # WHEN I add a new services with dependencies and a failed pre condition - State().add_service("test", 1, 1, PluginStatus.Inactive) - State().add_service("test2", 1, 1, PluginStatus.Inactive) - State().add_service("test1", 1, 1, PluginStatus.Inactive, 'test') - State().update_pre_conditions('test', False) - # THEN correct the state when I flush the preconditions - assert State().modules['test'].pass_preconditions is False - assert State().modules['test2'].pass_preconditions is False - assert State().modules['test1'].pass_preconditions is False - State().flush_preconditions() - assert State().modules['test'].pass_preconditions is False - assert State().modules['test2'].pass_preconditions is False - assert State().modules['test1'].pass_preconditions is False +def test_basic_preconditions_pass(state, registry): + # GIVEN a new state + Registry().register('test_plugin', MagicMock()) - def test_basic_preconditions_pass(self): - # GIVEN a new state - State().load_settings() - Registry().register('test_plugin', MagicMock()) + # WHEN I add a new services with dependencies and a failed pre condition + State().add_service("test", 1, 1, PluginStatus.Inactive) + State().add_service("test2", 1, 1, PluginStatus.Inactive) + State().add_service("test1", 1, 1, PluginStatus.Inactive, 'test') + State().update_pre_conditions('test', True) - # WHEN I add a new services with dependencies and a failed pre condition - State().add_service("test", 1, 1, PluginStatus.Inactive) - State().add_service("test2", 1, 1, PluginStatus.Inactive) - State().add_service("test1", 1, 1, PluginStatus.Inactive, 'test') - State().update_pre_conditions('test', True) - - # THEN correct the state when I flush the preconditions - assert State().modules['test'].pass_preconditions is True - assert State().modules['test2'].pass_preconditions is False - assert State().modules['test1'].pass_preconditions is False - State().flush_preconditions() - assert State().modules['test'].pass_preconditions is True - assert State().modules['test2'].pass_preconditions is False - assert State().modules['test1'].pass_preconditions is True + # THEN correct the state when I flush the preconditions + assert State().modules['test'].pass_preconditions is True + assert State().modules['test2'].pass_preconditions is False + assert State().modules['test1'].pass_preconditions is False + State().flush_preconditions() + assert State().modules['test'].pass_preconditions is True + assert State().modules['test2'].pass_preconditions is False + assert State().modules['test1'].pass_preconditions is True From a544aa11ff8e3cc5bb6dc56c151697a1a34c61c2 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 13 Feb 2020 20:57:51 +0000 Subject: [PATCH 2/3] Migrate display --- .../openlp_core/display/test_screens.py | 149 +++++++----------- 1 file changed, 58 insertions(+), 91 deletions(-) diff --git a/tests/functional/openlp_core/display/test_screens.py b/tests/functional/openlp_core/display/test_screens.py index 1788e2818..cae3bc010 100644 --- a/tests/functional/openlp_core/display/test_screens.py +++ b/tests/functional/openlp_core/display/test_screens.py @@ -21,111 +21,78 @@ """ Package to test the openlp.core.lib.screenlist package. """ -from unittest import TestCase from unittest.mock import MagicMock, patch -from PyQt5 import QtCore, QtWidgets +from PyQt5 import QtCore -from openlp.core.common.registry import Registry from openlp.core.display.screens import Screen, ScreenList -SCREEN = { - 'primary': False, - 'number': 1, - 'size': QtCore.QRect(0, 0, 1024, 768) -} +def test_current_display_screen(): + """ + Test that the "current" property returns the first display screen + """ + # GIVEN: A new ScreenList object with some screens + screen_list = ScreenList() + screen_list.screens = [ + Screen(number=0, geometry=QtCore.QRect(0, 0, 1024, 768), is_primary=True), + Screen(number=1, geometry=QtCore.QRect(1024, 0, 1024, 768), is_primary=False, is_display=True) + ] + + # WHEN: The current property is accessed + screen = screen_list.current + + # THEN: It should be the display screen + assert screen.number == 1 + assert screen.geometry == QtCore.QRect(1024, 0, 1024, 768) + assert screen.is_primary is False + assert screen.is_display is True -class TestScreenList(TestCase): +def test_current_primary_screen(): + """ + Test that the "current" property returns the first primary screen + """ + # GIVEN: A new ScreenList object with some screens + screen_list = ScreenList() + screen_list.screens = [ + Screen(number=0, geometry=QtCore.QRect(0, 0, 1024, 768), is_primary=True) + ] - def setUp(self): - """ - Set up the components need for all tests. - """ - # Mocked out desktop object - self.desktop = MagicMock() - self.desktop.primaryScreen.return_value = SCREEN['primary'] - self.desktop.screenCount.return_value = SCREEN['number'] - self.desktop.screenGeometry.return_value = SCREEN['size'] + # WHEN: The current property is accessed + screen = screen_list.current - self.application = QtWidgets.QApplication.instance() - Registry.create() - Registry().register('settings', MagicMock()) - self.application.setOrganizationName('OpenLP-tests') - self.application.setOrganizationDomain('openlp.org') - self.screens = ScreenList.create(self.desktop) + # THEN: It should be the display screen + assert screen.number == 0 + assert screen.geometry == QtCore.QRect(0, 0, 1024, 768) + assert screen.is_primary is True + assert screen.is_display is False - def tearDown(self): - """ - Delete QApplication. - """ - del self.screens - del self.application - def test_current_display_screen(self): - """ - Test that the "current" property returns the first display screen - """ - # GIVEN: A new ScreenList object with some screens - screen_list = ScreenList() - screen_list.screens = [ - Screen(number=0, geometry=QtCore.QRect(0, 0, 1024, 768), is_primary=True), - Screen(number=1, geometry=QtCore.QRect(1024, 0, 1024, 768), is_primary=False, is_display=True) - ] +@patch('openlp.core.display.screens.QtWidgets.QApplication.screens') +def test_create_screen_list(mocked_screens, settings): + """ + Create the screen list + """ + # GIVEN: Mocked desktop + mocked_desktop = MagicMock() + mocked_desktop.screenCount.return_value = 2 + mocked_desktop.primaryScreen.return_value = 0 + mocked_screens.return_value = [ + MagicMock(**{'geometry.return_value': QtCore.QRect(0, 0, 1024, 768)}), + MagicMock(**{'geometry.return_value': QtCore.QRect(1024, 0, 1024, 768)}) + ] - # WHEN: The current property is accessed - screen = screen_list.current + # WHEN: create() is called + screen_list = ScreenList.create(mocked_desktop) - # THEN: It should be the display screen - assert screen.number == 1 - assert screen.geometry == QtCore.QRect(1024, 0, 1024, 768) - assert screen.is_primary is False - assert screen.is_display is True - - def test_current_primary_screen(self): - """ - Test that the "current" property returns the first primary screen - """ - # GIVEN: A new ScreenList object with some screens - screen_list = ScreenList() - screen_list.screens = [ - Screen(number=0, geometry=QtCore.QRect(0, 0, 1024, 768), is_primary=True) - ] - - # WHEN: The current property is accessed - screen = screen_list.current - - # THEN: It should be the display screen - assert screen.number == 0 - assert screen.geometry == QtCore.QRect(0, 0, 1024, 768) - assert screen.is_primary is True - assert screen.is_display is False - - @patch('openlp.core.display.screens.QtWidgets.QApplication.screens') - def test_create_screen_list(self, mocked_screens): - """ - Create the screen list - """ - # GIVEN: Mocked desktop - mocked_desktop = MagicMock() - mocked_desktop.screenCount.return_value = 2 - mocked_desktop.primaryScreen.return_value = 0 - mocked_screens.return_value = [ - MagicMock(**{'geometry.return_value': QtCore.QRect(0, 0, 1024, 768)}), - MagicMock(**{'geometry.return_value': QtCore.QRect(1024, 0, 1024, 768)}) - ] - - # WHEN: create() is called - screen_list = ScreenList.create(mocked_desktop) - - # THEN: The correct screens have been set up - assert screen_list.screens[0].number == 0 - assert screen_list.screens[0].geometry == QtCore.QRect(0, 0, 1024, 768) - assert screen_list.screens[0].is_primary is True - assert screen_list.screens[1].number == 1 - assert screen_list.screens[1].geometry == QtCore.QRect(1024, 0, 1024, 768) - assert screen_list.screens[1].is_primary is False + # THEN: The correct screens have been set up + assert screen_list.screens[0].number == 0 + assert screen_list.screens[0].geometry == QtCore.QRect(0, 0, 1024, 768) + assert screen_list.screens[0].is_primary is True + assert screen_list.screens[1].number == 1 + assert screen_list.screens[1].geometry == QtCore.QRect(1024, 0, 1024, 768) + assert screen_list.screens[1].is_primary is False def test_screen_from_dict(): From dae7880604e91f6d37fca14cfa9f15df48a09be4 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 13 Feb 2020 21:04:15 +0000 Subject: [PATCH 3/3] Migrate lib part 1 --- tests/functional/openlp_core/lib/test_db.py | 239 +++++++++--------- .../openlp_core/lib/test_exceptions.py | 22 +- 2 files changed, 124 insertions(+), 137 deletions(-) diff --git a/tests/functional/openlp_core/lib/test_db.py b/tests/functional/openlp_core/lib/test_db.py index 584abb42e..633f1478b 100644 --- a/tests/functional/openlp_core/lib/test_db.py +++ b/tests/functional/openlp_core/lib/test_db.py @@ -21,10 +21,9 @@ """ Package to test the openlp.core.lib package. """ -import shutil +import pytest from pathlib import Path from tempfile import mkdtemp -from unittest import TestCase from unittest.mock import MagicMock, patch from sqlalchemy import MetaData @@ -34,142 +33,136 @@ from sqlalchemy.pool import NullPool from openlp.core.lib.db import delete_database, get_upgrade_op, init_db, upgrade_db -class TestDB(TestCase): +@pytest.fixture(scope='module') +def tmp_folder(): + tmp_folder = mkdtemp(prefix='openlp_') + return tmp_folder + + +def test_init_db_calls_correct_functions(): """ - A test case for all the tests for the :mod:`~openlp.core.lib.db` module. + Test that the init_db function makes the correct function calls """ - def setUp(self): - """ - Set up anything necessary for all tests - """ - self.tmp_folder = mkdtemp(prefix='openlp_') - - def tearDown(self): - """ - Clean up - """ - # Ignore errors since windows can have problems with locked files - shutil.rmtree(self.tmp_folder, ignore_errors=True) - - def test_init_db_calls_correct_functions(self): - """ - Test that the init_db function makes the correct function calls - """ - # GIVEN: Mocked out SQLAlchemy calls and return objects, and an in-memory SQLite database URL - with patch('openlp.core.lib.db.create_engine') as mocked_create_engine, \ - patch('openlp.core.lib.db.MetaData') as MockedMetaData, \ - patch('openlp.core.lib.db.sessionmaker') as mocked_sessionmaker, \ - patch('openlp.core.lib.db.scoped_session') as mocked_scoped_session: - mocked_engine = MagicMock() - mocked_metadata = MagicMock() - mocked_sessionmaker_object = MagicMock() - mocked_scoped_session_object = MagicMock() - mocked_create_engine.return_value = mocked_engine - MockedMetaData.return_value = mocked_metadata - mocked_sessionmaker.return_value = mocked_sessionmaker_object - mocked_scoped_session.return_value = mocked_scoped_session_object - db_url = 'sqlite://' - - # WHEN: We try to initialise the db - session, metadata = init_db(db_url) - - # THEN: We should see the correct function calls - mocked_create_engine.assert_called_with(db_url, poolclass=NullPool) - MockedMetaData.assert_called_with(bind=mocked_engine) - mocked_sessionmaker.assert_called_with(autoflush=True, autocommit=False, bind=mocked_engine) - mocked_scoped_session.assert_called_with(mocked_sessionmaker_object) - assert session is mocked_scoped_session_object, 'The ``session`` object should be the mock' - assert metadata is mocked_metadata, 'The ``metadata`` object should be the mock' - - def test_init_db_defaults(self): - """ - Test that initialising an in-memory SQLite database via ``init_db`` uses the defaults - """ - # GIVEN: An in-memory SQLite URL + # GIVEN: Mocked out SQLAlchemy calls and return objects, and an in-memory SQLite database URL + with patch('openlp.core.lib.db.create_engine') as mocked_create_engine, \ + patch('openlp.core.lib.db.MetaData') as MockedMetaData, \ + patch('openlp.core.lib.db.sessionmaker') as mocked_sessionmaker, \ + patch('openlp.core.lib.db.scoped_session') as mocked_scoped_session: + mocked_engine = MagicMock() + mocked_metadata = MagicMock() + mocked_sessionmaker_object = MagicMock() + mocked_scoped_session_object = MagicMock() + mocked_create_engine.return_value = mocked_engine + MockedMetaData.return_value = mocked_metadata + mocked_sessionmaker.return_value = mocked_sessionmaker_object + mocked_scoped_session.return_value = mocked_scoped_session_object db_url = 'sqlite://' - # WHEN: The database is initialised through init_db + # WHEN: We try to initialise the db session, metadata = init_db(db_url) - # THEN: Valid session and metadata objects should be returned - assert isinstance(session, ScopedSession), 'The ``session`` object should be a ``ScopedSession`` instance' - assert isinstance(metadata, MetaData), 'The ``metadata`` object should be a ``MetaData`` instance' + # THEN: We should see the correct function calls + mocked_create_engine.assert_called_with(db_url, poolclass=NullPool) + MockedMetaData.assert_called_with(bind=mocked_engine) + mocked_sessionmaker.assert_called_with(autoflush=True, autocommit=False, bind=mocked_engine) + mocked_scoped_session.assert_called_with(mocked_sessionmaker_object) + assert session is mocked_scoped_session_object, 'The ``session`` object should be the mock' + assert metadata is mocked_metadata, 'The ``metadata`` object should be the mock' - def test_get_upgrade_op(self): - """ - Test that the ``get_upgrade_op`` function creates a MigrationContext and an Operations object - """ - # GIVEN: Mocked out alembic classes and a mocked out SQLAlchemy session object - with patch('openlp.core.lib.db.MigrationContext') as MockedMigrationContext, \ - patch('openlp.core.lib.db.Operations') as MockedOperations: - mocked_context = MagicMock() - mocked_op = MagicMock() - mocked_connection = MagicMock() - MockedMigrationContext.configure.return_value = mocked_context - MockedOperations.return_value = mocked_op - mocked_session = MagicMock() - mocked_session.bind.connect.return_value = mocked_connection - # WHEN: get_upgrade_op is executed with the mocked session object - op = get_upgrade_op(mocked_session) +def test_init_db_defaults(): + """ + Test that initialising an in-memory SQLite database via ``init_db`` uses the defaults + """ + # GIVEN: An in-memory SQLite URL + db_url = 'sqlite://' - # THEN: The op object should be mocked_op, and the correction function calls should have been made - assert op is mocked_op, 'The return value should be the mocked object' - mocked_session.bind.connect.assert_called_with() - MockedMigrationContext.configure.assert_called_with(mocked_connection) - MockedOperations.assert_called_with(mocked_context) + # WHEN: The database is initialised through init_db + session, metadata = init_db(db_url) - def test_delete_database_without_db_file_name(self): - """ - Test that the ``delete_database`` function removes a database file, without the file name parameter - """ - # GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location - with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \ - patch('openlp.core.lib.db.delete_file') as mocked_delete_file: - MockedAppLocation.get_section_data_path.return_value = Path('test-dir') - mocked_delete_file.return_value = True - test_plugin = 'test' - test_location = Path('test-dir', test_plugin) + # THEN: Valid session and metadata objects should be returned + assert isinstance(session, ScopedSession), 'The ``session`` object should be a ``ScopedSession`` instance' + assert isinstance(metadata, MetaData), 'The ``metadata`` object should be a ``MetaData`` instance' - # WHEN: delete_database is run without a database file - result = delete_database(test_plugin) - # THEN: The AppLocation.get_section_data_path and delete_file methods should have been called - MockedAppLocation.get_section_data_path.assert_called_with(test_plugin) - mocked_delete_file.assert_called_with(test_location) - assert result is True, 'The result of delete_file should be True (was rigged that way)' +def test_get_upgrade_op(): + """ + Test that the ``get_upgrade_op`` function creates a MigrationContext and an Operations object + """ + # GIVEN: Mocked out alembic classes and a mocked out SQLAlchemy session object + with patch('openlp.core.lib.db.MigrationContext') as MockedMigrationContext, \ + patch('openlp.core.lib.db.Operations') as MockedOperations: + mocked_context = MagicMock() + mocked_op = MagicMock() + mocked_connection = MagicMock() + MockedMigrationContext.configure.return_value = mocked_context + MockedOperations.return_value = mocked_op + mocked_session = MagicMock() + mocked_session.bind.connect.return_value = mocked_connection - def test_delete_database_with_db_file_name(self): - """ - Test that the ``delete_database`` function removes a database file, with the file name supplied - """ - # GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location - with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \ - patch('openlp.core.lib.db.delete_file') as mocked_delete_file: - MockedAppLocation.get_section_data_path.return_value = Path('test-dir') - mocked_delete_file.return_value = False - test_plugin = 'test' - test_db_file = 'mydb.sqlite' - test_location = Path('test-dir', test_db_file) + # WHEN: get_upgrade_op is executed with the mocked session object + op = get_upgrade_op(mocked_session) - # WHEN: delete_database is run without a database file - result = delete_database(test_plugin, test_db_file) + # THEN: The op object should be mocked_op, and the correction function calls should have been made + assert op is mocked_op, 'The return value should be the mocked object' + mocked_session.bind.connect.assert_called_with() + MockedMigrationContext.configure.assert_called_with(mocked_connection) + MockedOperations.assert_called_with(mocked_context) - # THEN: The AppLocation.get_section_data_path and delete_file methods should have been called - MockedAppLocation.get_section_data_path.assert_called_with(test_plugin) - mocked_delete_file.assert_called_with(test_location) - assert result is False, 'The result of delete_file should be False (was rigged that way)' - def test_skip_db_upgrade_with_no_database(self): - """ - Test the upgrade_db function does not try to update a missing database - """ - # GIVEN: Database URL that does not (yet) exist - url = 'sqlite:///{tmp}/test_db.sqlite'.format(tmp=self.tmp_folder) - mocked_upgrade = MagicMock() +def test_delete_database_without_db_file_name(): + """ + Test that the ``delete_database`` function removes a database file, without the file name parameter + """ + # GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location + with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \ + patch('openlp.core.lib.db.delete_file') as mocked_delete_file: + MockedAppLocation.get_section_data_path.return_value = Path('test-dir') + mocked_delete_file.return_value = True + test_plugin = 'test' + test_location = Path('test-dir', test_plugin) - # WHEN: We attempt to upgrade a non-existant database - upgrade_db(url, mocked_upgrade) + # WHEN: delete_database is run without a database file + result = delete_database(test_plugin) - # THEN: upgrade should NOT have been called - assert mocked_upgrade.called is False, 'Database upgrade function should NOT have been called' + # THEN: The AppLocation.get_section_data_path and delete_file methods should have been called + MockedAppLocation.get_section_data_path.assert_called_with(test_plugin) + mocked_delete_file.assert_called_with(test_location) + assert result is True, 'The result of delete_file should be True (was rigged that way)' + + +def test_delete_database_with_db_file_name(): + """ + Test that the ``delete_database`` function removes a database file, with the file name supplied + """ + # GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location + with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \ + patch('openlp.core.lib.db.delete_file') as mocked_delete_file: + MockedAppLocation.get_section_data_path.return_value = Path('test-dir') + mocked_delete_file.return_value = False + test_plugin = 'test' + test_db_file = 'mydb.sqlite' + test_location = Path('test-dir', test_db_file) + + # WHEN: delete_database is run without a database file + result = delete_database(test_plugin, test_db_file) + + # THEN: The AppLocation.get_section_data_path and delete_file methods should have been called + MockedAppLocation.get_section_data_path.assert_called_with(test_plugin) + mocked_delete_file.assert_called_with(test_location) + assert result is False, 'The result of delete_file should be False (was rigged that way)' + + +def test_skip_db_upgrade_with_no_database(tmp_folder): + """ + Test the upgrade_db function does not try to update a missing database + """ + # GIVEN: Database URL that does not (yet) exist + url = 'sqlite:///{tmp}/test_db.sqlite'.format(tmp=tmp_folder) + mocked_upgrade = MagicMock() + + # WHEN: We attempt to upgrade a non-existent database + upgrade_db(url, mocked_upgrade) + + # THEN: upgrade should NOT have been called + assert mocked_upgrade.called is False, 'Database upgrade function should NOT have been called' diff --git a/tests/functional/openlp_core/lib/test_exceptions.py b/tests/functional/openlp_core/lib/test_exceptions.py index 6fc83cae2..fad55d5ff 100644 --- a/tests/functional/openlp_core/lib/test_exceptions.py +++ b/tests/functional/openlp_core/lib/test_exceptions.py @@ -21,24 +21,18 @@ """ Package to test the openlp.core.lib.exceptions package. """ -from unittest import TestCase - from openlp.core.lib.exceptions import ValidationError -class TestValidationError(TestCase): +def test_validation_error(): """ - Test the ValidationError Class + Test the creation of a ValidationError """ - def test_validation_error(self): - """ - Test the creation of a ValidationError - """ - # GIVEN: The ValidationError class + # GIVEN: The ValidationError class - # WHEN: Creating an instance of ValidationError - error = ValidationError('Test ValidationError') + # WHEN: Creating an instance of ValidationError + error = ValidationError('Test ValidationError') - # THEN: Then calling str on the error should return the correct text and it should be an instance of `Exception` - assert str(error) == 'Test ValidationError' - assert isinstance(error, Exception) + # THEN: Then calling str on the error should return the correct text and it should be an instance of `Exception` + assert str(error) == 'Test ValidationError' + assert isinstance(error, Exception)