def setUp(self): app_settings = MagicMock() self._temp_dir = TemporaryDirectory() url = "sqlite:///" + os.path.join(self._temp_dir.name, "db.sqlite") db_map = DiffDatabaseMapping(url, create=True) import_object_classes(db_map, ("class1",)) import_object_parameters(db_map, (("class1", "parameter1"), ("class1", "parameter2"))) import_objects(db_map, (("class1", "object1"), ("class1", "object2"))) import_object_parameter_values( db_map, ( ("class1", "object1", "parameter1", 1.0), ("class1", "object2", "parameter1", 3.0), ("class1", "object1", "parameter2", 5.0), ("class1", "object2", "parameter2", 7.0), ), ) db_map.commit_session("Add test data.") db_map.connection.close() with patch("spinetoolbox.spine_db_manager.SpineDBManager.thread", new_callable=PropertyMock) as mock_thread: mock_thread.return_value = QApplication.instance().thread() self._db_mngr = SpineDBManager(app_settings, None) with patch.object(SpineDBEditor, "restore_ui"): self._editor = SpineDBEditor(self._db_mngr, {url: db_map.codename}) object_class_index = self._editor.object_tree_model.index(0, 0) self._editor.object_tree_model.fetchMore(object_class_index) index = self._editor.object_tree_model.index(0, 0, object_class_index) self._editor.reload_pivot_table(index) self._model = self._editor.pivot_table_model self._model.start_fetching()
def setUp(self): """Overridden method. Runs before each test. Makes instance of SpineDBEditor class.""" with mock.patch( "spinetoolbox.spine_db_manager.QMessageBox" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ): self.mock_db_mngr = mock.MagicMock() self.mock_db_mngr.undo_action.__getitem__.side_effect = lambda key: QAction( ) self.mock_db_mngr.redo_action.__getitem__.side_effect = lambda key: QAction( ) self.mock_db_map = mock.MagicMock() self.mock_db_map.codename = "mock_db" self.ds_view_form = SpineDBEditor(self.mock_db_mngr, self.mock_db_map)
def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show" ): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 self.db_mngr = SpineDBManager(mock_settings, None) # TODO: Use a temp file? url = "sqlite:///test.sqlite" create_new_spine_database(url) self.db_mngr.fetch_db_maps_for_listener = lambda *args: None self.spine_db_editor = SpineDBEditor(self.db_mngr, {url: "db"}) self.db_map = self.spine_db_editor.first_db_map self.spine_db_editor.pivot_table_model = mock.MagicMock()
def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" self._temp_dir = TemporaryDirectory() url = "sqlite:///" + os.path.join(self._temp_dir.name, "test.sqlite") with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show" ): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 self.db_mngr = SpineDBManager(mock_settings, None) logger = mock.MagicMock() self.db_map = self.db_mngr.get_db_map(url, logger, codename="db", create=True) self.spine_db_editor = SpineDBEditor(self.db_mngr, {url: "db"}) self.spine_db_editor.pivot_table_model = mock.MagicMock()
def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" with mock.patch("spinetoolbox.spine_db_manager.DiffDatabaseMapping") as mock_DiffDBMapping, mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show"): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 self.db_mngr = SpineDBManager(mock_settings, None) self.db_mngr.fetch_db_maps_for_listener = lambda *args: None def DiffDBMapping_side_effect(url, codename=None, upgrade=False, create=False): mock_db_map = mock.MagicMock() mock_db_map.db_url = url mock_db_map.codename = codename return mock_db_map mock_DiffDBMapping.side_effect = DiffDBMapping_side_effect self.spine_db_editor = SpineDBEditor(self.db_mngr, {"mock_url": "mock_db"}) self.mock_db_map = self.spine_db_editor.first_db_map self.spine_db_editor.pivot_table_model = mock.MagicMock()
def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" self._temp_dir = TemporaryDirectory() url = "sqlite:///" + os.path.join(self._temp_dir.name, "test.sqlite") create_new_spine_database(url) with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show" ): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 with mock.patch( "spinetoolbox.spine_db_manager.SpineDBManager.thread", new_callable=mock.PropertyMock) as mock_thread: mock_thread.return_value = QApplication.instance().thread() self.db_mngr = SpineDBManager(mock_settings, None) self.spine_db_editor = SpineDBEditor(self.db_mngr, {url: "db"}) self.db_map = self.spine_db_editor.first_db_map self.spine_db_editor.pivot_table_model = mock.MagicMock()
def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show" ): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 self.db_mngr = SpineDBManager(mock_settings, None) self.db_mngr.fetch_db_maps_for_listener = lambda *args: None logger = mock.MagicMock() self.db_mngr.get_db_map("sqlite://", logger, codename="database", create=True) self.spine_db_editor = SpineDBEditor(self.db_mngr, {"sqlite://": "database"}) self.mock_db_map = self.spine_db_editor.first_db_map self.spine_db_editor.pivot_table_model = mock.MagicMock()
def setUp(self): app_settings = MagicMock() logger = MagicMock() with unittest.mock.patch( "spinetoolbox.spine_db_manager.SpineDBManager.thread", new_callable=PropertyMock) as mock_thread: mock_thread.return_value = QApplication.instance().thread() self._db_mngr = SpineDBManager(app_settings, None) self._db_editor = SpineDBEditor(self._db_mngr) self._db_map = self._db_mngr.get_db_map("sqlite://", logger, codename="test_db", create=True)
def setUp(self): db_mngr = MagicMock() # db_mngr.get_value.side_effect = lambda db_map, item_type, id_, field, role: id_ db_mngr.get_item.side_effect = lambda db_map, item_type, id_: { "name": id_, "parameter_name": id_ } db_mngr.get_value_index.side_effect = ( lambda db_map, item_type, id_, index, role: { "value1": { "index1": 5, "index2": -3 }, "value2": { "index1": 40, "index2": -24 }, }.get(id_, {}).get(index)) mock_db_map = Mock() mock_db_map.codename = "codename" db_mngr.undo_action.__getitem__.side_effect = lambda key: QAction() db_mngr.redo_action.__getitem__.side_effect = lambda key: QAction() with patch.object(SpineDBEditor, "restore_ui"): tabular_view = SpineDBEditor(db_mngr, mock_db_map) self._model = IndexExpansionPivotTableModel(tabular_view) data = { ('node1', 'unitA', 'index1', 'parameter1', 'alternative1'): 'value1', ('node1', 'unitB', 'index2', 'parameter1', 'alternative1'): 'value1', ('node2', 'unitA', 'index1', 'parameter1', 'alternative1'): 'value2', ('node2', 'unitB', 'index2', 'parameter1', 'alternative1'): 'value2', } tabular_view.load_expanded_parameter_value_data = lambda: data object_class_ids = {'node': 1, 'unit': 2} self._model.call_reset_model(object_class_ids) self._model.start_fetching()
def setUp(self): db_mngr = MagicMock() db_mngr.get_value.side_effect = lambda db_map, item_type, id_, field, role: id_ db_mngr.get_item.side_effect = lambda db_map, item_type, id_: { "name": id_, "parameter_name": id_ } mock_db_map = Mock() mock_db_map.codename = "codename" db_mngr.undo_action.__getitem__.side_effect = lambda key: QAction() db_mngr.redo_action.__getitem__.side_effect = lambda key: QAction() with patch.object(SpineDBEditor, "restore_ui"): tabular_view = SpineDBEditor(db_mngr, mock_db_map) self._model = ParameterValuePivotTableModel(tabular_view) data = { ('object1', 'parameter1', 'alternative1'): '1', ('object2', 'parameter1', 'alternative1'): '3', ('object1', 'parameter2', 'alternative1'): '5', ('object2', 'parameter2', 'alternative1'): '7', } tabular_view.load_parameter_value_data = lambda: data object_class_ids = {'object_class': 1} self._model.call_reset_model(object_class_ids) self._model.start_fetching()
class TestAddItemsDialog(unittest.TestCase): @classmethod def setUpClass(cls): """Overridden method. Runs once before all tests in this class.""" try: cls.app = QApplication().processEvents() except RuntimeError: pass logging.basicConfig( stream=sys.stderr, level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', ) def setUp(self): """Overridden method. Runs before each test. Makes instance of SpineDBEditor class.""" with mock.patch( "spinetoolbox.spine_db_manager.QMessageBox" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ): self.mock_db_mngr = mock.MagicMock() self.mock_db_mngr.undo_action.__getitem__.side_effect = lambda key: QAction( ) self.mock_db_mngr.redo_action.__getitem__.side_effect = lambda key: QAction( ) self.mock_db_map = mock.MagicMock() self.mock_db_map.codename = "mock_db" self.ds_view_form = SpineDBEditor(self.mock_db_mngr, self.mock_db_map) def tearDown(self): """Overridden method. Runs after each test. Use this to free resources after a test if needed. """ with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.save_window_state" ) as mock_save_w_s: self.ds_view_form.close() mock_save_w_s.assert_called_once() self.ds_view_form.deleteLater() self.ds_view_form = None try: os.remove('mock_db.sqlite') except OSError: pass def test_add_object_classes(self): """Test object classes are added through the manager when accepting the dialog.""" dialog = AddObjectClassesDialog(self.ds_view_form, self.mock_db_mngr, self.mock_db_map) model = dialog.model header = model.header model.fetchMore() self.assertEqual( header, ['object_class name', 'description', 'display icon', 'databases']) indexes = [ model.index(0, header.index(field)) for field in ('object_class name', 'databases') ] values = ['fish', 'mock_db'] model.batch_set_data(indexes, values) def _add_object_classes(db_map_data): self.assertTrue(self.mock_db_map in db_map_data) data = db_map_data[self.mock_db_map] self.assertEqual(len(data), 1) item = data[0] self.assertTrue("name" in item) self.assertEqual(item["name"], "fish") self.mock_db_mngr.add_object_classes.side_effect = _add_object_classes dialog.accept() self.mock_db_mngr.add_object_classes.assert_called_once() def test_do_not_add_object_classes_with_invalid_db(self): """Test object classes aren't added when the database is not correct.""" dialog = AddObjectClassesDialog(self.ds_view_form, self.mock_db_mngr, self.mock_db_map) self.ds_view_form.msg_error = mock.NonCallableMagicMock() self.ds_view_form.msg_error.attach_mock(mock.MagicMock(), "emit") model = dialog.model header = model.header model.fetchMore() self.assertEqual( header, ['object_class name', 'description', 'display icon', 'databases']) indexes = [ model.index(0, header.index(field)) for field in ('object_class name', 'databases') ] values = ['fish', 'gibberish'] model.batch_set_data(indexes, values) dialog.accept() self.mock_db_mngr.add_object_classes.assert_not_called() self.ds_view_form.msg_error.emit.assert_called_with( "Invalid database 'gibberish' at row 1")
class TestSpineDBEditorWithDBMapping(unittest.TestCase): @classmethod def setUpClass(cls): """Overridden method. Runs once before all tests in this class.""" try: cls.app = QApplication().processEvents() except RuntimeError: pass logging.basicConfig( stream=sys.stderr, level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', ) def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" self._temp_dir = TemporaryDirectory() url = "sqlite:///" + os.path.join(self._temp_dir.name, "test.sqlite") with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show" ): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 self.db_mngr = SpineDBManager(mock_settings, None) logger = mock.MagicMock() self.db_map = self.db_mngr.get_db_map(url, logger, codename="db", create=True) self.spine_db_editor = SpineDBEditor(self.db_mngr, {url: "db"}) self.spine_db_editor.pivot_table_model = mock.MagicMock() def tearDown(self): """Overridden method. Runs after each test. Use this to free resources after a test if needed. """ with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.save_window_state" ) as mock_save_w_s, mock.patch( "spinetoolbox.spine_db_manager.QMessageBox"): self.spine_db_editor.close() mock_save_w_s.assert_called_once() QApplication.removePostedEvents( None) # Clean up unfinished fetcher signals self.db_mngr.close_all_sessions() self.db_mngr.clean_up() self.db_mngr = None # Ensure the database file is closed to allow the temporary directory to be removed. self.spine_db_editor.deleteLater() self.spine_db_editor = None self._temp_dir.cleanup() def fetch_object_tree_model(self): for item in self.spine_db_editor.object_tree_model.visit_all(): if item.can_fetch_more(): item.fetch_more() def test_duplicate_object_in_object_tree_model(self): data = dict() data["object_classes"] = ["fish", "dog"] data["relationship_classes"] = [("fish__dog", ("fish", "dog"))] data["objects"] = [("fish", "nemo"), ("dog", "pluto")] data["relationships"] = [("fish__dog", ("nemo", "pluto"))] data["object_parameters"] = [("fish", "color")] data["object_parameter_values"] = [("fish", "nemo", "color", "orange")] with mock.patch( "spinetoolbox.spine_db_manager.SpineDBManager.entity_class_icon" ) as mock_icon: mock_icon.return_value = None loop = QEventLoop() self.db_mngr.data_imported.connect(loop.quit) self.db_mngr.import_data({self.db_map: data}) loop.exec_() loop.deleteLater() mock_icon.assert_called() self.fetch_object_tree_model() root_item = self.spine_db_editor.object_tree_model.root_item fish_item = next( iter(item for item in root_item.children if item.display_data == "fish")) nemo_item = fish_item.child(0) with mock.patch( "spinetoolbox.spine_db_editor.widgets.tree_view_mixin.QInputDialog" ) as mock_input_dialog: mock_input_dialog.getText.side_effect = lambda *args, **kwargs: ( "nemo_copy", True) loop = QEventLoop() self.db_mngr.data_imported.connect(loop.quit) self.spine_db_editor.duplicate_object(nemo_item.index()) loop.exec_() loop.deleteLater() nemo_dupe = fish_item.child(1) self.assertEqual(nemo_dupe.display_data, "nemo_copy")
class TestSpineDBEditor( TestSpineDBEditorAddMixin, TestSpineDBEditorUpdateMixin, TestSpineDBEditorRemoveMixin, TestSpineDBEditorFilterMixin, unittest.TestCase, ): @staticmethod def _object_class(*args): return dict(zip(["id", "name", "description", "display_order", "display_icon"], args)) @staticmethod def _object(*args): return dict(zip(["id", "class_id", "name", "description"], args)) @staticmethod def _relationship_class(*args): return dict(zip(["id", "name", "object_class_id_list", "object_class_name_list"], args)) @staticmethod def _relationship(*args): return dict( zip( ["id", "class_id", "name", "class_name", "object_class_id_list", "object_id_list", "object_name_list"], args, ) ) @staticmethod def _object_parameter_definition(*args): d = dict(zip(["id", "object_class_id", "object_class_name", "parameter_name"], args)) return d @staticmethod def _relationship_parameter_definition(*args): d = dict( zip( [ "id", "relationship_class_id", "relationship_class_name", "object_class_id_list", "object_class_name_list", "parameter_name", ], args, ) ) return d @staticmethod def _object_parameter_value(*args): d = dict( zip( [ "id", "object_class_id", "object_class_name", "object_id", "object_name", "parameter_id", "parameter_name", "value", ], args, ) ) d["entity_id"] = d["object_id"] return d @staticmethod def _relationship_parameter_value(*args): d = dict( zip( [ "id", "relationship_class_id", "relationship_class_name", "object_class_id_list", "object_class_name_list", "relationship_id", "object_id_list", "object_name_list", "parameter_id", "parameter_name", "value", ], args, ) ) d["entity_id"] = d["relationship_id"] return d @classmethod def setUpClass(cls): """Overridden method. Runs once before all tests in this class.""" try: cls.app = QApplication().processEvents() except RuntimeError: pass logging.basicConfig( stream=sys.stderr, level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', ) cls.create_mock_dataset() @classmethod def create_mock_dataset(cls): cls.fish_class = cls._object_class(1, "fish", "A fish.", 1, None) cls.dog_class = cls._object_class(2, "dog", "A dog.", 3, None) cls.fish_dog_class = cls._relationship_class( 3, "fish__dog", str(cls.fish_class["id"]) + "," + str(cls.dog_class["id"]), cls.fish_class["name"] + "," + cls.dog_class["name"], ) cls.dog_fish_class = cls._relationship_class( 4, "dog__fish", str(cls.dog_class["id"]) + "," + str(cls.fish_class["id"]), cls.dog_class["name"] + "," + cls.fish_class["name"], ) cls.nemo_object = cls._object(1, cls.fish_class["id"], 'nemo', 'The lost one.') cls.pluto_object = cls._object(2, cls.dog_class["id"], 'pluto', "Mickey's.") cls.scooby_object = cls._object(3, cls.dog_class["id"], 'scooby', 'Scooby-Dooby-Doo.') cls.pluto_nemo_rel = cls._relationship( 4, cls.dog_fish_class["id"], "dog__fish_pluto__nemo", cls.dog_fish_class["name"], str(cls.dog_class["id"]) + "," + str(cls.fish_class["id"]), str(cls.pluto_object["id"]) + "," + str(cls.nemo_object["id"]), cls.pluto_object["name"] + "," + cls.nemo_object["name"], ) cls.nemo_pluto_rel = cls._relationship( 5, cls.fish_dog_class["id"], "fish__dog_nemo__pluto", cls.fish_dog_class["name"], str(cls.fish_class["id"]) + "," + str(cls.dog_class["id"]), str(cls.nemo_object["id"]) + "," + str(cls.pluto_object["id"]), cls.nemo_object["name"] + "," + cls.pluto_object["name"], ) cls.nemo_scooby_rel = cls._relationship( 6, cls.fish_dog_class["id"], "fish__dog_nemo__scooby", cls.fish_dog_class["name"], str(cls.fish_class["id"]) + "," + str(cls.dog_class["id"]), str(cls.nemo_object["id"]) + "," + str(cls.scooby_object["id"]), cls.nemo_object["name"] + "," + cls.scooby_object["name"], ) cls.water_parameter = cls._object_parameter_definition(1, cls.fish_class["id"], cls.fish_class["name"], "water") cls.breed_parameter = cls._object_parameter_definition(2, cls.dog_class["id"], cls.dog_class["name"], "breed") cls.relative_speed_parameter = cls._relationship_parameter_definition( 3, cls.fish_dog_class["id"], cls.fish_dog_class["name"], cls.fish_dog_class["object_class_id_list"], cls.fish_dog_class["object_class_name_list"], "relative_speed", ) cls.combined_mojo_parameter = cls._relationship_parameter_definition( 4, cls.dog_fish_class["id"], cls.dog_fish_class["name"], cls.dog_fish_class["object_class_id_list"], cls.dog_fish_class["object_class_name_list"], "combined_mojo", ) cls.nemo_water = cls._object_parameter_value( 1, cls.water_parameter["object_class_id"], cls.water_parameter["object_class_name"], cls.nemo_object["id"], cls.nemo_object["name"], cls.water_parameter["id"], cls.water_parameter["parameter_name"], '"salt"', ) cls.pluto_breed = cls._object_parameter_value( 2, cls.breed_parameter["object_class_id"], cls.breed_parameter["object_class_name"], cls.pluto_object["id"], cls.pluto_object["name"], cls.breed_parameter["id"], cls.breed_parameter["parameter_name"], '"bloodhound"', ) cls.scooby_breed = cls._object_parameter_value( 3, cls.breed_parameter["object_class_id"], cls.breed_parameter["object_class_name"], cls.scooby_object["id"], cls.scooby_object["name"], cls.breed_parameter["id"], cls.breed_parameter["parameter_name"], '"great dane"', ) cls.nemo_pluto_relative_speed = cls._relationship_parameter_value( 4, cls.relative_speed_parameter["relationship_class_id"], cls.relative_speed_parameter["relationship_class_name"], cls.relative_speed_parameter["object_class_id_list"], cls.relative_speed_parameter["object_class_name_list"], cls.nemo_pluto_rel["id"], cls.nemo_pluto_rel["object_id_list"], cls.nemo_pluto_rel["object_name_list"], cls.relative_speed_parameter["id"], cls.relative_speed_parameter["parameter_name"], "-1", ) cls.nemo_scooby_relative_speed = cls._relationship_parameter_value( 5, cls.relative_speed_parameter["relationship_class_id"], cls.relative_speed_parameter["relationship_class_name"], cls.relative_speed_parameter["object_class_id_list"], cls.relative_speed_parameter["object_class_name_list"], cls.nemo_scooby_rel["id"], cls.nemo_scooby_rel["object_id_list"], cls.nemo_scooby_rel["object_name_list"], cls.relative_speed_parameter["id"], cls.relative_speed_parameter["parameter_name"], "5", ) cls.pluto_nemo_combined_mojo = cls._relationship_parameter_value( 6, cls.combined_mojo_parameter["relationship_class_id"], cls.combined_mojo_parameter["relationship_class_name"], cls.combined_mojo_parameter["object_class_id_list"], cls.combined_mojo_parameter["object_class_name_list"], cls.pluto_nemo_rel["id"], cls.pluto_nemo_rel["object_id_list"], cls.pluto_nemo_rel["object_name_list"], cls.combined_mojo_parameter["id"], cls.combined_mojo_parameter["parameter_name"], "100", ) def setUp(self): """Overridden method. Runs before each test. Makes instances of SpineDBEditor classes.""" with mock.patch("spinetoolbox.spine_db_manager.DiffDatabaseMapping") as mock_DiffDBMapping, mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui" ), mock.patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.show"): mock_settings = mock.Mock() mock_settings.value.side_effect = lambda *args, **kwards: 0 self.db_mngr = SpineDBManager(mock_settings, None) self.db_mngr.fetch_db_maps_for_listener = lambda *args: None def DiffDBMapping_side_effect(url, codename=None, upgrade=False, create=False): mock_db_map = mock.MagicMock() mock_db_map.db_url = url mock_db_map.codename = codename return mock_db_map mock_DiffDBMapping.side_effect = DiffDBMapping_side_effect self.spine_db_editor = SpineDBEditor(self.db_mngr, {"mock_url": "mock_db"}) self.mock_db_map = self.spine_db_editor.first_db_map self.spine_db_editor.pivot_table_model = mock.MagicMock() def tearDown(self): """Overridden method. Runs after each test. Use this to free resources after a test if needed. """ with mock.patch( "spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.save_window_state" ) as mock_save_w_s, mock.patch("spinetoolbox.spine_db_manager.QMessageBox"): self.spine_db_editor.close() mock_save_w_s.assert_called_once() self.spine_db_editor.db_mngr.stop_fetchers() QApplication.removePostedEvents(None) # Clean up unfinished fetcher signals self.spine_db_editor.deleteLater() self.spine_db_editor = None def put_mock_object_classes_in_db_mngr(self): """Put fish and dog object classes in the db mngr.""" object_classes = [self.fish_class, self.dog_class] self.db_mngr.object_classes_added.emit({self.mock_db_map: object_classes}) def put_mock_objects_in_db_mngr(self): """Put nemo, pluto and scooby objects in the db mngr.""" objects = [self.nemo_object, self.pluto_object, self.scooby_object] self.db_mngr.objects_added.emit({self.mock_db_map: objects}) def put_mock_relationship_classes_in_db_mngr(self): """Put dog__fish and fish__dog relationship classes in the db mngr.""" relationship_classes = [self.fish_dog_class, self.dog_fish_class] self.db_mngr.relationship_classes_added.emit({self.mock_db_map: relationship_classes}) def put_mock_relationships_in_db_mngr(self): """Put pluto_nemo, nemo_pluto and nemo_scooby relationships in the db mngr.""" relationships = [self.pluto_nemo_rel, self.nemo_pluto_rel, self.nemo_scooby_rel] self.db_mngr.relationships_added.emit({self.mock_db_map: relationships}) def put_mock_object_parameter_definitions_in_db_mngr(self): """Put water and breed object parameter definitions in the db mngr.""" parameter_definitions = [self.water_parameter, self.breed_parameter] with mock.patch.object(CompoundParameterModel, "_modify_data_in_filter_menus"): self.db_mngr.parameter_definitions_added.emit({self.mock_db_map: parameter_definitions}) def put_mock_relationship_parameter_definitions_in_db_mngr(self): """Put relative speed and combined mojo relationship parameter definitions in the db mngr.""" parameter_definitions = [self.relative_speed_parameter, self.combined_mojo_parameter] with mock.patch.object(CompoundParameterModel, "_modify_data_in_filter_menus"): self.db_mngr.parameter_definitions_added.emit({self.mock_db_map: parameter_definitions}) def put_mock_object_parameter_values_in_db_mngr(self): """Put some object parameter values in the db mngr.""" parameter_values = [self.nemo_water, self.pluto_breed, self.scooby_breed] with mock.patch.object(CompoundParameterModel, "_modify_data_in_filter_menus"): self.db_mngr.parameter_values_added.emit({self.mock_db_map: parameter_values}) def put_mock_relationship_parameter_values_in_db_mngr(self): """Put some relationship parameter values in the db mngr.""" parameter_values = [ self.nemo_pluto_relative_speed, self.nemo_scooby_relative_speed, self.pluto_nemo_combined_mojo, ] with mock.patch.object(CompoundParameterModel, "_modify_data_in_filter_menus"): self.db_mngr.parameter_values_added.emit({self.mock_db_map: parameter_values}) def put_mock_dataset_in_db_mngr(self): """Put mock dataset in the db mngr.""" self.put_mock_object_classes_in_db_mngr() self.put_mock_objects_in_db_mngr() self.put_mock_relationship_classes_in_db_mngr() self.put_mock_relationships_in_db_mngr() self.put_mock_object_parameter_definitions_in_db_mngr() self.put_mock_relationship_parameter_definitions_in_db_mngr() self.put_mock_object_parameter_values_in_db_mngr() self.put_mock_relationship_parameter_values_in_db_mngr() self.fetch_object_tree_model() def fetch_object_tree_model(self): for item in self.spine_db_editor.object_tree_model.visit_all(): if item.can_fetch_more(): item.fetch_more() def test_set_object_parameter_definition_defaults(self): """Test that defaults are set in object parameter_definition models according the object tree selection.""" self.spine_db_editor.init_models() self.put_mock_object_classes_in_db_mngr() self.fetch_object_tree_model() # Select fish item in object tree root_item = self.spine_db_editor.object_tree_model.root_item fish_item = root_item.child(0) fish_index = self.spine_db_editor.object_tree_model.index_from_item(fish_item) self.spine_db_editor.ui.treeView_object.setCurrentIndex(fish_index) self.spine_db_editor.ui.treeView_object.selectionModel().select(fish_index, QItemSelectionModel.Select) # Check default in object parameter_definition model = self.spine_db_editor.object_parameter_definition_model model.empty_model.fetchMore() h = model.header.index row_data = [] for row in range(model.rowCount()): row_data.append(tuple(model.index(row, h(field)).data() for field in ("object_class_name", "database"))) self.assertTrue(("fish", "mock_db") in row_data) @unittest.skip("TODO") def test_set_object_parameter_value_defaults(self): """Test that defaults are set in relationship parameter_definition models according the object tree selection. """ self.fail() @unittest.skip("TODO") def test_set_relationship_parameter_definition_defaults(self): """Test that defaults are set in relationship parameter_definition models according the object tree selection. """ self.fail() @unittest.skip("TODO") def test_set_relationship_parameter_value_defaults(self): """Test that defaults are set in relationship parameter_definition models according the object tree selection. """ self.fail()
class TestParameterValuePivotTableModel(unittest.TestCase): @classmethod def setUpClass(cls): if not QApplication.instance(): QApplication() def setUp(self): app_settings = MagicMock() self._temp_dir = TemporaryDirectory() url = "sqlite:///" + os.path.join(self._temp_dir.name, "db.sqlite") db_map = DiffDatabaseMapping(url, create=True) import_object_classes(db_map, ("class1",)) import_object_parameters(db_map, (("class1", "parameter1"), ("class1", "parameter2"))) import_objects(db_map, (("class1", "object1"), ("class1", "object2"))) import_object_parameter_values( db_map, ( ("class1", "object1", "parameter1", 1.0), ("class1", "object2", "parameter1", 3.0), ("class1", "object1", "parameter2", 5.0), ("class1", "object2", "parameter2", 7.0), ), ) db_map.commit_session("Add test data.") db_map.connection.close() with patch("spinetoolbox.spine_db_manager.SpineDBManager.thread", new_callable=PropertyMock) as mock_thread: mock_thread.return_value = QApplication.instance().thread() self._db_mngr = SpineDBManager(app_settings, None) with patch.object(SpineDBEditor, "restore_ui"): self._editor = SpineDBEditor(self._db_mngr, {url: db_map.codename}) object_class_index = self._editor.object_tree_model.index(0, 0) self._editor.object_tree_model.fetchMore(object_class_index) index = self._editor.object_tree_model.index(0, 0, object_class_index) self._editor.reload_pivot_table(index) self._model = self._editor.pivot_table_model self._model.start_fetching() def tearDown(self): self._db_mngr.close_all_sessions() self._db_mngr.clean_up() self._temp_dir.cleanup() def test_x_flag(self): self.assertIsNone(self._model.plot_x_column) self._model.set_plot_x_column(1, True) self.assertEqual(self._model.plot_x_column, 1) self._model.set_plot_x_column(1, False) self.assertIsNone(self._model.plot_x_column) def test_header_name(self): self.assertEqual(self._model.rowCount(), 5) self.assertEqual(self._model.columnCount(), 4) self.assertEqual(self._model.header_name(self._model.index(2, 0)), 'object1') self.assertEqual(self._model.header_name(self._model.index(0, 1)), 'parameter1') self.assertEqual(self._model.header_name(self._model.index(3, 0)), 'object2') self.assertEqual(self._model.header_name(self._model.index(0, 2)), 'parameter2') def test_data(self): self.assertEqual(self._model.rowCount(), 5) self.assertEqual(self._model.columnCount(), 4) self.assertEqual(self._model.index(0, 0).data(), "parameter") self.assertEqual(self._model.index(1, 0).data(), "class1") self.assertEqual(self._model.index(2, 0).data(), "object1") self.assertEqual(self._model.index(3, 0).data(), "object2") self.assertEqual(self._model.index(4, 0).data(), None) self.assertEqual(self._model.index(0, 1).data(), "parameter1") self.assertEqual(self._model.index(1, 1).data(), None) self.assertEqual(self._model.index(2, 1).data(), str(1.0)) self.assertEqual(self._model.index(3, 1).data(), str(3.0)) self.assertEqual(self._model.index(4, 1).data(), None) self.assertEqual(self._model.index(0, 2).data(), "parameter2") self.assertEqual(self._model.index(1, 2).data(), None) self.assertEqual(self._model.index(2, 2).data(), str(5.0)) self.assertEqual(self._model.index(3, 2).data(), str(7.0)) self.assertEqual(self._model.index(4, 2).data(), None) self.assertEqual(self._model.index(0, 3).data(), None) self.assertEqual(self._model.index(1, 3).data(), None) self.assertEqual(self._model.index(2, 3).data(), None) self.assertEqual(self._model.index(3, 3).data(), None) self.assertEqual(self._model.index(4, 3).data(), None) def test_header_row_count(self): self.assertEqual(self._model.headerRowCount(), 2)
class TestIndexExpansionPivotTableModel(unittest.TestCase): @classmethod def setUpClass(cls): if not QApplication.instance(): QApplication() def setUp(self): app_settings = MagicMock() self._temp_dir = TemporaryDirectory() url = "sqlite:///" + os.path.join(self._temp_dir.name, "db.sqlite") db_map = DiffDatabaseMapping(url, create=True) import_object_classes(db_map, ("class1",)) import_object_parameters(db_map, (("class1", "parameter1"), ("class1", "parameter2"))) import_objects(db_map, (("class1", "object1"), ("class1", "object2"))) import_object_parameter_values( db_map, ( ("class1", "object1", "parameter1", Map(["A", "B"], [1.1, 2.1])), ("class1", "object2", "parameter1", Map(["C", "D"], [1.2, 2.2])), ("class1", "object1", "parameter2", Map(["C", "D"], [-1.1, -2.1])), ("class1", "object2", "parameter2", Map(["A", "B"], [-1.2, -2.2])), ), ) db_map.commit_session("Add test data.") db_map.connection.close() with patch("spinetoolbox.spine_db_manager.SpineDBManager.thread", new_callable=PropertyMock) as mock_thread: mock_thread.return_value = QApplication.instance().thread() self._db_mngr = SpineDBManager(app_settings, None) with patch.object(SpineDBEditor, "restore_ui"): self._editor = SpineDBEditor(self._db_mngr, {url: db_map.codename}) object_class_index = self._editor.object_tree_model.index(0, 0) self._editor.object_tree_model.fetchMore(object_class_index) index = self._editor.object_tree_model.index(0, 0, object_class_index) for action in self._editor.pivot_action_group.actions(): if action.text() == self._editor._INDEX_EXPANSION: action.trigger() break self._editor.reload_pivot_table(index) self._model = self._editor.pivot_table_model self._model.start_fetching() def tearDown(self): self._db_mngr.close_all_sessions() self._db_mngr.clean_up() self._temp_dir.cleanup() def test_data(self): self.assertEqual(self._model.rowCount(), 11) self.assertEqual(self._model.columnCount(), 5) model_data = list() i = self._model.index for row in range(11): model_data.append(list(i(row, column).data() for column in range(5))) expected = [ [None, "parameter", "parameter1", "parameter2", None], ["class1", "index", None, None, None], ["object1", "A", str(1.1), None, None], ["object1", "B", str(2.1), None, None], ["object2", "C", str(1.2), None, None], ["object2", "D", str(2.2), None, None], ["object1", "C", None, str(-1.1), None], ["object1", "D", None, str(-2.1), None], ["object2", "A", None, str(-1.2), None], ["object2", "B", None, str(-2.2), None], [None, None, None, None, None], ] self.assertEqual(model_data, expected)
def _make_pivot_proxy_model(): """Returns a prefilled PivotTableModel.""" db_mngr = MagicMock() db_mngr.get_value.side_effect = lambda db_map, item_type, id_, role: from_database( id_) mock_db_map = MagicMock() mock_db_map.codename = "codename" db_mngr.undo_action.__getitem__.side_effect = lambda key: QAction() db_mngr.redo_action.__getitem__.side_effect = lambda key: QAction() with patch.object(SpineDBEditor, "restore_ui"), patch.object(SpineDBEditor, "show"): spine_db_editor = SpineDBEditor(db_mngr, mock_db_map) spine_db_editor.create_header_widget = lambda *args, **kwargs: None simple_map = Map(["a", "b"], [-1.1, -2.2]) nested_map = Map( ["a", "b"], [ Map([DateTime("2020-11-13T11:00"), DateTime("2020-11-13T12:00")], [-1.1, -2.2]), Map([DateTime("2020-11-13T11:00"), DateTime("2020-11-13T12:00")], [-3.3, -4.4]), ], ) nested_map_with_time_series = Map( ["a", "b"], [ Map( [DateTime("2020-11-13T11:00"), DateTime("2020-11-13T12:00")], [ TimeSeriesVariableResolution( ["2020-11-13T11:00", "2020-11-13T12:00"], [-1.1, -2.2], False, False), TimeSeriesVariableResolution( ["2020-11-13T12:00", "2020-11-13T13:00"], [-3.3, -4.4], False, False), ], ), Map( [DateTime("2020-11-13T11:00"), DateTime("2020-11-13T12:00")], [ TimeSeriesVariableResolution( ["2020-11-13T11:00", "2020-11-13T12:00"], [-5.5, -6.6], False, False), TimeSeriesVariableResolution( ["2020-11-13T12:00", "2020-11-13T13:00"], [-7.7, -8.8], False, False), ], ), ], ) data = { ('1', 'int_col', 'base_alternative'): '-3', ('2', 'int_col', 'base_alternative'): '-1', ('3', 'int_col', 'base_alternative'): '2', ('1', 'float_col', 'base_alternative'): '1.1', ('2', 'float_col', 'base_alternative'): '1.2', ('3', 'float_col', 'base_alternative'): '1.3', ( '1', 'time_series_col', 'base_alternative', ): '{"type": "time_series", "data": {"2019-07-10T13:00": 2.3, "2019-07-10T13:20": 5.0}}', ( '2', 'time_series_col', 'base_alternative', ): '{"type": "time_series", "index": {"start": "2019-07-10T13:00", "resolution": "20 minutes"}, "data": [3.3, 4.0]}', ( '3', 'time_series_col', 'base_alternative', ): '{"type": "time_series", "data": {"2019-07-10T13:00": 4.3, "2019-07-10T13:20": 3.0}}', ("1", "map_col", "base_alternative"): to_database(simple_map), ("2", "map_col", "base_alternative"): to_database(nested_map), ("3", "map_col", "base_alternative"): to_database(nested_map_with_time_series), } data = { tuple((db, k) for k in key) + (db, ): (db, value) for key, value in data.items() } spine_db_editor.load_parameter_value_data = lambda: data spine_db_editor.pivot_table_model = model = ParameterValuePivotTableModel( spine_db_editor) with patch.object( SpineDBEditor, "current_object_class_ids", new_callable=PropertyMock) as mock_current_object_class_ids: mock_current_object_class_ids.return_value = {"object": {db: 1}} model.call_reset_model(pivot=(['object'], ['parameter', 'alternative'], ['database'], (db, ))) model.start_fetching() spine_db_editor.pivot_table_model = model spine_db_editor.pivot_table_proxy.setSourceModel(model) return spine_db_editor.pivot_table_proxy