Initial github release

This commit is contained in:
Lea Laux
2020-11-18 11:13:49 +01:00
committed by KDV Admin
commit 49de912c15
77 changed files with 14165 additions and 0 deletions

View File

@@ -0,0 +1,220 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication, QLabel, QListWidget
from pygadmin.widgets.command_history import CommandHistoryDialog
from pygadmin.command_history_store import global_command_history_store
from pygadmin.configurator import global_app_configurator
class TestCommandHistoryDialogMethods(unittest.TestCase):
"""
Test the functionality and methods of the command history dialog.
"""
def test_empty_dialog(self):
"""
Test the dialog without data in the command history store, so the dialog shows a warning about the empty
history.
"""
# Get the current command history for saving it during the testing of the method. Later, the current command
# history is saved again in the command history store.
current_command_history = global_command_history_store.get_command_history_from_yaml_file()
# Delete all commands from the history, so the history is empty. As a result, the dialog should show the warning
# ui.
global_command_history_store.delete_all_commands_from_history()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a command history dialog.
command_history_dialog = CommandHistoryDialog()
# Check for the existence and correct instance of the empty label.
assert isinstance(command_history_dialog.empty_label, QLabel)
# Set the list with the data about the last commands as command history list.
global_command_history_store.command_history_list = current_command_history
# Save the list in the yaml file again.
global_command_history_store.commit_current_list_to_yaml()
def test_initial_attributes(self):
"""
Test the initial attributes of the dialog (with an existing command history).
"""
# Define a dictionary with a command and the information about it, so there is at least one command in the
# command history.
command_dictionary = {"Command": "SELECT * FROM test;",
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2020-10-01 11:53:59",
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
global_command_history_store.save_command_history_in_yaml_file(command_dictionary)
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a command history dialog.
command_history_dialog = CommandHistoryDialog()
# Check for the GUI attributes, so the QListWidget and the QLabels.
assert isinstance(command_history_dialog.history_list_widget, QListWidget)
assert isinstance(command_history_dialog.command_label, QLabel)
assert isinstance(command_history_dialog.connection_identifier_label, QLabel)
assert isinstance(command_history_dialog.date_time_label, QLabel)
# The data list of the table model should be empty at the beginning.
assert command_history_dialog.table_model.data_list == []
# Check for the existence and correct instance of the command history list.
assert isinstance(global_command_history_store.command_history_list, list)
# Clean up, so the testing command is no longer part of the command history store.
global_command_history_store.delete_command_from_history(command_dictionary)
def test_show_command_information_in_labels(self):
"""
Test the method for showing the command information in the given labels and the table view, so the data list of
the table model is checked.
"""
# Define a dictionary with a command and the information about it, so there is at least one command in the
# command history.
command_dictionary = {"Command": "SELECT * FROM test;",
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2019-05-04 13:37:00",
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
global_command_history_store.save_command_history_in_yaml_file(command_dictionary)
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a command history dialog.
command_history_dialog = CommandHistoryDialog()
# Define an index for the last item for iterating. This index is used later for setting the current row as
# selection.
index_of_last_item = 0
# Define an identifier text for finding the command of the previous defined command dictionary.
command_identifier_text = "{}\n{}".format(command_dictionary["Command"], command_dictionary["Time"])
# Iterate over every item in the list widget.
for item_count in range(command_history_dialog.history_list_widget.count()):
# If the text of the current item is the same as in the command identifier text, use the current item count
# as index of the last item.
if command_identifier_text == command_history_dialog.history_list_widget.item(item_count).text():
index_of_last_item = item_count
# End the loop, because further iterating is not necessary. There is already a match.
break
# Set the index of the last item as current row.
command_history_dialog.history_list_widget.setCurrentRow(index_of_last_item)
# Check the labels and the data list of the tree model for the correct list.
assert command_history_dialog.command_label.text() == command_dictionary["Command"]
assert command_history_dialog.connection_identifier_label.text() == command_dictionary["Identifier"]
assert command_history_dialog.date_time_label.text() == command_dictionary["Time"]
assert command_history_dialog.table_model.data_list == command_dictionary["Result"]
# Clean up, so the testing command is no longer part of the command history store.
global_command_history_store.delete_command_from_history(command_dictionary)
def test_get_command_dictionary_of_current_selected_identifier(self):
"""
Test the method for getting the command dictionary of the current selected identifier in the history list
widget.
"""
# Define a dictionary with a command and the information about it, so there is at least one command in the
# command history.
command_dictionary = {"Command": "SELECT * FROM test;",
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2019-05-04 13:37:00",
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
global_command_history_store.save_command_history_in_yaml_file(command_dictionary)
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a command history dialog.
command_history_dialog = CommandHistoryDialog()
# Define an index for the last item for iterating. This index is used later for setting the current row as
# selection.
index_of_last_item = 0
# Define an identifier text for finding the command of the previous defined command dictionary.
command_identifier_text = "{}\n{}".format(command_dictionary["Command"], command_dictionary["Time"])
# Iterate over every item in the list widget.
for item_count in range(command_history_dialog.history_list_widget.count()):
# If the text of the current item is the same as in the command identifier text, use the current item count
# as index of the last item.
if command_identifier_text == command_history_dialog.history_list_widget.item(item_count).text():
index_of_last_item = item_count
# End the loop, because further iterating is not necessary. There is already a match.
break
# Set the index of the last item as current row.
command_history_dialog.history_list_widget.setCurrentRow(index_of_last_item)
# Get the command dictionary of the selected command.
selected_command_dictionary = command_history_dialog.get_command_dictionary_of_current_selected_identifier()
# The dictionary of the selected item should be the command dictionary.
assert selected_command_dictionary == command_dictionary
# Clean up, so the testing command is no longer part of the command history store.
global_command_history_store.delete_command_from_history(command_dictionary)
def test_save_current_command_limit(self):
"""
Test the function for saving the current command limit with the input in the line edit.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a command history dialog.
command_history_dialog = CommandHistoryDialog()
# Define a new command limit.
new_command_limit = 15
# Set the command limit as string as text of the command limit line edit.
command_history_dialog.command_limit_line_edit.setText(str(new_command_limit))
# Save the current command limit.
command_history_dialog.save_current_command_limit()
# The command limit in the app configurator should now be the pre-defined new command limit.
assert global_app_configurator.get_single_configuration("command_limit") == new_command_limit
def test_check_valid_command_limit(self):
"""
Test the function for checking a valid comment limit in the command limit line edit.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a command history dialog.
command_history_dialog = CommandHistoryDialog()
# A normal text, which is not equivalent to None and cannot be casted to an integer, should be invalid.
command_history_dialog.command_limit_line_edit.setText("test")
assert command_history_dialog.check_valid_command_limit() is False
# -1 as text can be casted to an integer, but the command limit needs to be larger than 0.
command_history_dialog.command_limit_line_edit.setText("-1")
assert command_history_dialog.check_valid_command_limit() is False
# The text None should be accepted.
command_history_dialog.command_limit_line_edit.setText("None")
assert command_history_dialog.check_valid_command_limit() is True
# The text 42 can be casted to a valid integer value.
command_history_dialog.command_limit_line_edit.setText("42")
assert command_history_dialog.check_valid_command_limit() is True

View File

@@ -0,0 +1,169 @@
import unittest
import os
from pygadmin.command_history_store import global_command_history_store
from pygadmin.configurator import global_app_configurator
class TestCommandHistoryStoreMethods(unittest.TestCase):
"""
Test the command history store with its method and its behavior.
"""
def test_path_of_command_history_file(self):
"""
Check for the existence of the yaml file, which stores the command history.
"""
assert os.path.exists(global_command_history_store.yaml_command_history_file)
def test_command_history_list(self):
"""
Test the existence and the correct type of the command history list.
"""
assert isinstance(global_command_history_store.command_history_list, list)
def test_get_command_history_from_yaml_file(self):
"""
Test the behavior of the method for getting the current command history from the yaml file.
"""
# Get the current list.
command_history_list = global_command_history_store.get_command_history_from_yaml_file()
# The result of the method should be the current data list of the command history store.
assert command_history_list == global_command_history_store.command_history_list
def test_commit_current_list_to_yaml(self):
"""
Test the correct commit of the current list to the yaml file.
"""
# Ensure the correct load of all previous commands in the history.
global_command_history_store.get_command_history_from_yaml_file()
# The result of committing should be True for a success.
assert global_command_history_store.commit_current_list_to_yaml() is True
def test_save_command_history_in_yaml_file(self):
"""
Test the function for saving one specific command in the command history.
"""
# Define a dictionary with a command and the information about it.
command_dictionary = {"Command": "SELECT * FROM test;",
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2020-10-01 11:53:59",
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
# Save the command dictionary in the yaml file.
global_command_history_store.save_command_history_in_yaml_file(command_dictionary)
# Now the dictionary should be part of the command history list.
assert command_dictionary in global_command_history_store.command_history_list
# Clean up, so the testing command is no longer part of the command history store.
global_command_history_store.delete_command_from_history(command_dictionary)
def test_delete_command_from_history(self):
"""
Test the deletion of a command from the history.
"""
# Define a dictionary with a command and the information about it.
command_dictionary = {"Command": "SELECT * FROM test;",
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2020-10-01 11:53:59",
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
# Save the command dictionary in the yaml file.
global_command_history_store.save_command_history_in_yaml_file(command_dictionary)
# The deletion of the dictionary should return True as a success.
assert global_command_history_store.delete_command_from_history(command_dictionary) is True
# A second try with the same dictionary should return False, because the dictionary is already deleted and can
# not be found.
assert global_command_history_store.delete_command_from_history(command_dictionary) is False
def test_delete_all_commands_from_history(self):
"""
Test the deletion of the complete history.
"""
# Get the current command history for saving it again later.
current_command_history = global_command_history_store.get_command_history_from_yaml_file()
# The deletion of the whole history should be successful.
assert global_command_history_store.delete_all_commands_from_history() is True
assert global_command_history_store.command_history_list == []
# Set the previous saved list as command history list for restoring the correct list.
global_command_history_store.command_history_list = current_command_history
# Save the correct list in the yaml file.
global_command_history_store.commit_current_list_to_yaml()
def test_get_new_command_limit(self):
"""
Test the method for getting the new command limit in the command history store.
"""
# Define a command limit.
command_limit = 100
# Set the command limit in the global app configurator.
global_app_configurator.set_single_configuration("command_limit", command_limit)
global_app_configurator.save_configuration_data()
# Get the new command limit as attribute of the class.
global_command_history_store.get_new_command_limit()
# The command limit of the global history store should be the command limit, which was set before.
assert global_command_history_store.command_limit == command_limit
def test_adjust_saved_history_to_new_command_limit(self):
"""
Test the method for adjusting an existing list of commands in the history to a new command limit.
"""
# Define a previous command limit.
old_command_limit = 100
# Set the command limit in the global app configurator.
global_app_configurator.set_single_configuration("command_limit", old_command_limit)
global_app_configurator.save_configuration_data()
# Define a new command limit.
command_limit = 10
# Add new command dictionaries to the command history.
for command_number in range(command_limit + 2):
# Define a unique command dictionary.
command_dictionary = {"Command": "{}".format(command_number),
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2020-10-01 11:53:{}".format(command_number),
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
# Save the unique command dictionary in the command history store.
global_command_history_store.save_command_history_in_yaml_file(command_dictionary)
# Set the command limit in the global app configurator.
global_app_configurator.set_single_configuration("command_limit", command_limit)
global_app_configurator.save_configuration_data()
# Use the function for adjusting the saved history to the new command list and commit the new list to the yaml
# file.
global_command_history_store.adjust_saved_history_to_new_command_limit()
global_command_history_store.commit_current_list_to_yaml()
# The length of the list should be the command limit.
assert len(global_command_history_store.command_history_list) == command_limit
# Define a test command dictionary. This dictionary was inserted before, but it was too old, so it should be
# deleted.
test_command_dictionary = {"Command": "1",
"Identifier": "testuser@testserver:5432/testdb",
"Time": "2020-10-01 11:53:1",
"Result": [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"],
["row D", "row E", "row F"]]}
# The test dictionary should not be part of the command history list, because it is deleted.
assert test_command_dictionary not in global_command_history_store.command_history_list

View File

@@ -0,0 +1,107 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QCheckBox, QLineEdit
from pygadmin.configurator import global_app_configurator
from pygadmin.widgets.configuration_settings import ConfigurationSettingsDialog
class TestConfigurationSettingsDialogMethods(unittest.TestCase):
"""
Test the functionality and methods of the configuration settings dialog.
"""
def test_initial_attributes(self):
"""
Test the correct class and the initial attributes of the configuration settings dialog.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an dialog.
configuration_settings_dialog = ConfigurationSettingsDialog()
# Check the correct instance.
assert isinstance(configuration_settings_dialog, QDialog)
# Check for the correct instance of the configuration dictionary.
assert isinstance(configuration_settings_dialog.configuration_dictionary, dict)
def test_save_current_configuration(self):
"""
Test the save of the current configuration: Check the text or check box status of the GUI elements and their
correct save in the dictionary.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
configuration_settings_dialog = ConfigurationSettingsDialog()
# The function should return True for a success.
assert configuration_settings_dialog.save_current_configuration() is True
# Check the correct save of every user input.
for description, gui_elements in configuration_settings_dialog.configuration_dictionary.items():
# The dialog shows the configurations in a more readable version.
description = description.replace(" ", "_")
# Get the current configuration.
configuration = global_app_configurator.get_single_configuration(description)
# The second element of gui_elements contains the element for user interaction, so this one is checked.
user_element = gui_elements[1]
# Check for a QCheckBox as potential element.
if isinstance(user_element, QCheckBox):
# Check for the correct configuration.
assert user_element.isChecked() == configuration
# Check for a QLineEdit as potential element.
elif isinstance(user_element, QLineEdit):
# Check for the correct configuration.
assert configuration == user_element.text()
def test_save_current_configuration_and_close(self):
"""
Test the method for saving the current configuration and close after that.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
configuration_settings_dialog = ConfigurationSettingsDialog()
# Ensure a visible dialog.
assert configuration_settings_dialog.isVisible() is True
# Save the configuration and close the dialog.
configuration_settings_dialog.save_current_configuration_and_close()
# The dialog should be invisible after a close.
assert configuration_settings_dialog.isVisible() is False
def test_check_for_unsaved_configurations(self):
"""
Test the method for checking for unsaved configurations.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
configuration_settings_dialog = ConfigurationSettingsDialog()
# At this moment, all configurations are saved/freshly initialized.
assert configuration_settings_dialog.check_for_unsaved_configuration() is False
# Change one existing element, so there are unsaved configurations.
for gui_elements in configuration_settings_dialog.configuration_dictionary.values():
# The second element is the element for user interaction.
user_element = gui_elements[1]
# Check for a checkbox.
if isinstance(user_element, QCheckBox):
# Get the current state of the checkbox.
current_state = user_element.isChecked()
# Reverse the state, so there is an unsaved configuration now.
user_element.setChecked(not current_state)
# Check for an unsaved configuration. This should be True.
assert configuration_settings_dialog.check_for_unsaved_configuration() is True
# Break the loop after an assertion.
break

152
tests/test_configurator.py Normal file
View File

@@ -0,0 +1,152 @@
import unittest
import os
from pygadmin.configurator import global_app_configurator
class TestConfiguratorMethods(unittest.TestCase):
"""
Test the app configurator with its methods and behavior.
"""
def test_path_of_configuration_files(self):
"""
Test the existence of the two file paths.
"""
# Get the path for the general configuration file and test it.
configuration_file = global_app_configurator.yaml_app_configuration_file
assert os.path.exists(configuration_file)
# Get the path for the editor style configuration file and test it.
editor_style_file = global_app_configurator.yaml_editor_style_configuration_file
assert os.path.exists(editor_style_file)
def test_configuration_dictionary(self):
"""
Test the correct load of the configuration dictionary.
"""
assert global_app_configurator.configuration_dictionary is not None
assert isinstance(global_app_configurator.configuration_dictionary, dict)
def test_style_configuration_dictionary(self):
"""
Test the correct load of the editor style dictionary.
"""
assert global_app_configurator.editor_style_dictionary is not None
assert isinstance(global_app_configurator.editor_style_dictionary, dict)
def test_save_configuration_data(self):
"""
Test the save of all current configuration data, which should return True for a success.
"""
assert global_app_configurator.save_configuration_data() is True
def test_save_style_data(self):
"""
Test the save of all current style data, which should return True for a success.
"""
assert global_app_configurator.save_style_configuration_data() is True
def test_get_all_current_configurations(self):
"""
Test getting all current configurations. The result should be a dict.
"""
assert isinstance(global_app_configurator.get_all_current_configurations(), dict)
def test_get_all_current_style_themes(self):
"""
Test getting all current style themes and the correct structure of the returning dictionary.
"""
# Get the style dictionary.
style_dictionary = global_app_configurator.get_all_current_color_style_themes()
# Test for the right instance.
assert isinstance(style_dictionary, dict)
# Test every value in the dictionary for the correct instance, which should also be a dictionary.
for value in style_dictionary.values():
assert isinstance(value, dict)
def test_set_single_configuration(self):
"""
Set a single configuration and test for correct setting with direct access to the dictionary.
"""
# Define a key and a value for testing.
test_key = "test"
test_value = True
# Set the configuration.
global_app_configurator.set_single_configuration(test_key, test_value)
# Get the value to the key with direct access to the dictionary.
assert global_app_configurator.configuration_dictionary[test_key] is test_value
def test_get_single_configuration(self):
"""
Set a single configuration and test for the correct setting and getting with the method of the app configurator.
"""
# Define a test key and a test value.
test_key = "test"
test_value = True
# Set the configuration.
global_app_configurator.set_single_configuration(test_key, test_value)
# Get the value to the key with the method of the app configurator.
assert global_app_configurator.get_single_configuration(test_key) is test_value
def test_delete_configuration(self):
"""
Set a configuration and delete the configuration again for testing the correct deletion. Test also the case for
a non existing configuration.
"""
# Define a test key and a test value.
test_key = "test"
test_value = True
# Set the configuration.
global_app_configurator.set_single_configuration(test_key, test_value)
# Delete the configuration based on its key and check if the result is True for a successful deletion.
assert global_app_configurator.delete_single_configuration(test_key) is True
# Delete the configuration based on its key again, which should fail, so the result is False.
assert global_app_configurator.delete_single_configuration(test_key) is False
def test_get_all_configurations(self):
"""
Test to get all components and check the correctness with direct access.
"""
configurations = global_app_configurator.get_all_current_configurations()
assert configurations == global_app_configurator.configuration_dictionary
def test_default_color_theme(self):
"""
Test to get the default color theme.
"""
# Get the color theme out of the global app configurator.
color_theme = global_app_configurator.get_single_configuration("color_theme")
# Proceed, if the editor style dictionary and the color theme is not None. So there are elements in the style
# dictionary and there is a color theme.
if global_app_configurator.editor_style_dictionary and color_theme:
# Get the style description and the style values (as a dictionary).
style_description, style_values = global_app_configurator.get_default_color_theme_style()
# The first value should be the color theme,
assert style_description == color_theme
# The second value should contain a dictionary with the different color themes.
assert isinstance(style_values, dict)
# If the color theme or the style dictionary (or both) is None or empty, the result for the default color theme
# should also be None.
else:
assert global_app_configurator.get_default_color_theme_style() is None

View File

@@ -0,0 +1,503 @@
import sys
import unittest
import keyring
from PyQt5.QtWidgets import QApplication, QLineEdit, QListWidgetItem
from pygadmin.widgets.connection_dialog import ConnectionDialogWidget
from pygadmin.connectionstore import global_connection_store
class TestConnectionDialogMethods(unittest.TestCase):
"""
Test the functionality and methods of the connection dialog in some essential aspects.
"""
def test_initial_attributes(self):
"""
Test basic attributes of the class after initializing.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Check for the connection parameter edit dictionary, which is an essential element to the dialog.
assert isinstance(connection_dialog.connection_parameter_edit_dictionary, dict)
# Check every value in the dictionary for a QLineEdit.
for value in connection_dialog.connection_parameter_edit_dictionary.values():
# The elements should be QLineEdits.
assert isinstance(value, QLineEdit)
# The label for the status for testing the given connection should have the correct text.
assert connection_dialog.test_given_connection_status_label.text() == "Not tested yet"
def test_check_for_empty_parameter_fields(self):
"""
Test the function for checking for empty parameter fields.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Get the current result for the check of empty parameter fields. It should not be a simple boolean, so it will
# be a list.
empty_parameter_result = connection_dialog.check_for_empty_parameter_edit_fields()
# The first parameter of the result list is a boolean, which should be True in this case.
assert empty_parameter_result[0] is True
# Set to every edit field a value.
for edit_field in connection_dialog.connection_parameter_edit_dictionary.values():
edit_field.setText("42")
# After setting values to every edit field, there should not be an empty parameter edit field.
assert connection_dialog.check_for_empty_parameter_edit_fields() is False
def test_check_for_valid_port(self):
"""
Test the function for checking for a valid port in the port line edit.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Get the port line edit.
port_line_edit = connection_dialog.connection_parameter_edit_dictionary["Port"]
# Set a string, which can not be casted to an int, as text for the port.
port_line_edit.setText("This is a triumph. I'm making a note here, huge success.")
# The check for a valid port should be False.
assert connection_dialog.check_for_valid_port() is False
# Set a string, which can be casted to an int, as text for the port. The int in this case is invalid.
port_line_edit.setText("-42")
# The check for a valid port should still be False.
assert connection_dialog.check_for_valid_port() is False
# Set a valid and an int, which can be casted to int, as port.
port_line_edit.setText("42")
# The check for a valid port should now be True.
assert connection_dialog.check_for_valid_port() is True
def test_check_for_changed_password(self):
"""
Test the method for checking for a changed password in the QLineEdit for the password compared to the password
in the password manager.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Define the name of the service.
service = "Pygadmin"
# Define the identifier for the password
password_identifier = "testuser@random:5432"
# Choose a password.
password = "unsafe"
# Set the password in the keyring.
keyring.set_password(service, password_identifier, password)
# Get the line edit for the password.
password_line_edit = connection_dialog.connection_parameter_edit_dictionary["Password"]
# Set the currently saved password as text.
password_line_edit.setText(password)
# The function for checking for a changed password should now be False.
assert connection_dialog.check_for_changed_password(password_identifier) is False
# Change the text in the password line edit to another password.
password_line_edit.setText("unsafe again")
# Now there should be a changed password compared to the password manager, so the result should be True.
assert connection_dialog.check_for_changed_password(password_identifier) is True
# Clean up, so the password identifier and the password for testing are not a part of the password manager.
keyring.delete_password(service, password_identifier)
def test_set_password_with_identifier(self):
"""
Test the method for setting a password with its identifier.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Define the identifier for the password
password_identifier = "testuser@random:5432"
# Get the password line edit.
password_line_edit = connection_dialog.connection_parameter_edit_dictionary["Password"]
# Set a text as password in the password line edit.
password_line_edit.setText("unsafe")
# The function for setting the password with its identifier should be True.
assert connection_dialog.set_password_with_its_identifier(password_identifier) is True
# Clean up, so the password identifier and the password for testing are not a part of the password manager.
keyring.delete_password("Pygadmin", password_identifier)
def test_valid_find_occurrence_in_list_widget_and_select_item(self):
"""
Test the method for finding the occurrence of an item in a list widget. The item should be selected after the
call of the method. Use valid connection parameters, which are also part of the connection store.
"""
# Define a connection dictionary for saving the connection data in the connection store and creating a
# connection identifier later, so the connection is part of the list widget and can be selected.
connection_dictionary = {"Host": "random",
"Username": "testuser",
"Port": 5432,
"Database": "postgres"}
# Save the connection in the connection store.
global_connection_store.save_connection_parameters_in_yaml_file(connection_dictionary)
# Save the current connections in the connection store in the yaml file.
global_connection_store.commit_current_list_to_yaml()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Define a connection identifier for selecting it in the list widget.
connection_identifier = "{}@{}:{}/{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"], connection_dictionary["Database"])
# Get the item related to the connection identifier.
item = connection_dialog.find_occurrence_in_list_widget_and_select_item(connection_identifier)
# The item should be a QListWidgetItem.
assert isinstance(item, QListWidgetItem)
# The text of the item should be the connection identifier.
assert item.text() == connection_identifier
# Get the list of selected items.
selected_items = connection_dialog.connection_parameters_list_widget.selectedItems()
# Only one item should be selected, so the list should contain only one element.
assert len(selected_items) == 1
# Get the selected item.
selected_item = selected_items[0]
# The selected item should be the item, which is returned by the function.
assert selected_item == item
# Clean up, so the test connection is no longer part of the connection store.
global_connection_store.delete_connection(connection_dictionary)
global_connection_store.commit_current_list_to_yaml()
def test_invalid_find_occurrence_in_list_widget_and_select_item(self):
"""
Test the method for finding the occurrence of an item in a list widget. Use invalid connection parameters for
testing the error case, so the connection identifier is not based on existing connection parameters in the
connection store.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Get a non existing item in the list widget.
item = connection_dialog.find_occurrence_in_list_widget_and_select_item(None)
# The item should be None.
assert item is None
# Check for the selected items in the list widget.
selected_items = connection_dialog.connection_parameters_list_widget.selectedItems()
# The list of selected items should be empty.
assert selected_items == []
def test_get_all_item_texts_in_list_widget(self):
"""
Test the method for getting all the texts of the items/connection identifiers in the list widget.
"""
# Create a list for storing all connection identifiers.
connection_identifiers = []
# Use every dictionary of a connection in the connection store to create an identifier for the connection.
for connection_dictionary in global_connection_store.connection_parameters_yaml:
# Create the connection identifier.
identifier = "{}@{}:{}/{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"], connection_dictionary["Database"])
# Append the identifier to the list of connection identifiers.
connection_identifiers.append(identifier)
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Get all item texts.
item_texts = connection_dialog.get_all_item_texts_in_list_widget()
# Iterate over every identifier for checking its existence in the item texts.
for identifier in connection_identifiers:
# The identifier should be part of the item texts.
assert identifier in item_texts
def test_method_for_testing_database_connection(self):
"""
Test the method for testing for a valid database connection based on the current text in the QLineEdits.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# The text of the connection status label should be "Not tested yet", because a connection is not tested.
assert connection_dialog.test_given_connection_status_label.text() == "Not tested yet"
# Set valid connection parameters for testing a connection.
connection_dialog.connection_parameter_edit_dictionary["Host"].setText("localhost")
connection_dialog.connection_parameter_edit_dictionary["Username"].setText("testuser")
connection_dialog.connection_parameter_edit_dictionary["Database"].setText("postgres")
connection_dialog.connection_parameter_edit_dictionary["Port"].setText("5432")
# Test the connection with the method.
connection_dialog.test_current_database_connection()
# The label should now show a valid database connection, because valid parameters are used.
assert connection_dialog.test_given_connection_status_label.text() == "Connection Valid"
# Set a new text as host, so after a new test, the connection is invalid.
connection_dialog.connection_parameter_edit_dictionary["Host"].setText("localhorst")
# After changing the text, the label should switch back to "Not tested yet"
assert connection_dialog.test_given_connection_status_label.text() == "Not tested yet"
# Test the database connection now.
connection_dialog.test_current_database_connection()
# The label should now show an invalid connection.
assert connection_dialog.test_given_connection_status_label.text() == "Connection Invalid"
def test_insert_parameters_in_edit_fields(self):
"""
Test the method for inserting parameters in the QLineEdit fields based on the signal for a change in the
selection of the list widget.
"""
# Define a connection dictionary for saving the connection data in the connection store and creating a
# connection identifier later, so the connection is part of the list widget and can be selected.
connection_dictionary = {"Host": "random",
"Username": "testuser",
"Port": 5432,
"Database": "postgres"}
# Save the connection in the connection store.
global_connection_store.save_connection_parameters_in_yaml_file(connection_dictionary)
# Save the current connections in the connection store in the yaml file.
global_connection_store.commit_current_list_to_yaml()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Define a connection identifier for selecting it in the list widget.
connection_identifier = "{}@{}:{}/{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"], connection_dictionary["Database"])
# Select the item based on the connection identifier in the list widget.
connection_dialog.find_occurrence_in_list_widget_and_select_item(connection_identifier)
# Check the correct content of the QLineEdit fields. They should contain the parameters of the connection
# dictionary.
assert connection_dictionary["Host"] == connection_dialog.connection_parameter_edit_dictionary["Host"].text()
assert connection_dictionary["Username"] \
== connection_dialog.connection_parameter_edit_dictionary["Username"].text()
# Cast the port to string, because it is saved in the dictionary as integer.
assert str(connection_dictionary["Port"]) \
== connection_dialog.connection_parameter_edit_dictionary["Port"].text()
assert connection_dictionary["Database"] \
== connection_dialog.connection_parameter_edit_dictionary["Database"].text()
# Clean up, so the test connection is no longer part of the connection store.
global_connection_store.delete_connection(connection_dictionary)
global_connection_store.commit_current_list_to_yaml()
def test_get_selected_connection(self):
"""
Test the function for getting the selected connection, which returns a boolean and sets a result as an
attribute.
"""
# Define a connection dictionary for saving the connection data in the connection store and creating a
# connection identifier later, so the connection is part of the list widget and can be selected.
connection_dictionary = {"Host": "random",
"Username": "testuser",
"Port": 5432,
"Database": "postgres"}
# Save the connection in the connection store.
global_connection_store.save_connection_parameters_in_yaml_file(connection_dictionary)
# Save the current connections in the connection store in the yaml file.
global_connection_store.commit_current_list_to_yaml()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# A selected connection is missing, so the method should return False.
assert connection_dialog.get_selected_connection() is False
# Define a connection identifier for selecting it in the list widget.
connection_identifier = "{}@{}:{}/{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"], connection_dictionary["Database"])
# Select the item related to the connection identifier.
connection_dialog.find_occurrence_in_list_widget_and_select_item(connection_identifier)
# Now the method should return True, because an identifier is selected.
assert connection_dialog.get_selected_connection() is True
# The dictionary of the selected connection should be the pre-defined connection dictionary.
assert connection_dialog.selected_connection_parameters_dictionary == connection_dictionary
# Clean up, so the test connection is no longer part of the connection store.
global_connection_store.delete_connection(connection_dictionary)
global_connection_store.commit_current_list_to_yaml()
def test_valid_delete_selected_connection(self):
"""
Test the method for deleting the selected database connection with a saved database connection.
"""
# Define a connection dictionary for saving the connection data in the connection store and creating a
# connection identifier later, so the connection is part of the list widget and can be selected.
connection_dictionary = {"Host": "random",
"Username": "testuser",
"Port": 5432,
"Database": "postgres"}
# Define a password identifier for setting a password, so it can be deleted.
password_identifier = "{}@{}:{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"])
keyring.set_password("Pygadmin", password_identifier, "test")
# Save the connection in the connection store.
global_connection_store.save_connection_parameters_in_yaml_file(connection_dictionary)
# Save the current connections in the connection store in the yaml file.
global_connection_store.commit_current_list_to_yaml()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Clean up, so the test connection is no longer part of the connection store.
global_connection_store.delete_connection(connection_dictionary)
global_connection_store.commit_current_list_to_yaml()
# Define a connection identifier for selecting it in the list widget.
connection_identifier = "{}@{}:{}/{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"], connection_dictionary["Database"])
# Select the item related to the connection identifier.
connection_dialog.find_occurrence_in_list_widget_and_select_item(connection_identifier)
# The deletion of the selected connection should return True.
assert connection_dialog.delete_selected_connection() is True
def test_invalid_delete_selected_connection(self):
"""
Test the method for deleting the selected database connection with an unsaved database connection.
"""
# Define a connection dictionary for saving the connection data in the connection store and creating a
# connection identifier later, so the connection is part of the list widget and can be selected.
connection_dictionary = {"Host": "random",
"Username": "testuser",
"Port": 5432,
"Database": "postgres"}
# Save the connection in the connection store.
global_connection_store.save_connection_parameters_in_yaml_file(connection_dictionary)
# Save the current connections in the connection store in the yaml file.
global_connection_store.commit_current_list_to_yaml()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Clean up, so the test connection is no longer part of the connection store.
global_connection_store.delete_connection(connection_dictionary)
global_connection_store.commit_current_list_to_yaml()
# Define a connection identifier for selecting it in the list widget.
connection_identifier = "{}@{}:{}/{}".format(connection_dictionary["Username"], connection_dictionary["Host"],
connection_dictionary["Port"], connection_dictionary["Database"])
# Select the item related to the connection identifier.
connection_dialog.find_occurrence_in_list_widget_and_select_item(connection_identifier)
# The deletion of the selected connection should not return True.
assert connection_dialog.delete_selected_connection() is not True
def test_check_for_valid_timeout(self):
"""
Test the method for checking for a valid timeout.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Set the text to an empty string, so a cast to an integer is not possible.
connection_dialog.timeout_line_edit.setText("")
# The timeout should be invalid.
assert connection_dialog.check_for_valid_timeout() is False
# Set the text to an invalid integer value.
connection_dialog.timeout_line_edit.setText("-42")
# The timeout should still be invalid.
assert connection_dialog.check_for_valid_timeout() is False
# Set the text to a valid integer value.
connection_dialog.timeout_line_edit.setText("42")
# The result should now be True.
assert connection_dialog.check_for_valid_timeout() is True
def test_port_checkbox(self):
"""
Test the correct behavior of the (de)activation of the checkbox for using the standard postgres port.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a dialog.
connection_dialog = ConnectionDialogWidget()
# Get the use postgres port checkbox of the dialog.
postgres_port_checkbox = connection_dialog.use_postgres_port_checkbox
# Get the port line edit.
port_line_edit = connection_dialog.connection_parameter_edit_dictionary["Port"]
# Set the checkbox unchecked.
postgres_port_checkbox.setChecked(False)
# Now the port line edit should be empty.
assert port_line_edit.text() == ""
# Define a port text for further testing.
port_text = "1337"
# Set the text as current text of the port line edit field.
port_line_edit.setText(port_text)
# Set the port checkbox to checked.
postgres_port_checkbox.setChecked(True)
# Now the port line edit should contain the standard postgres port as text.
assert port_line_edit.text() == "5432"
# Set the port checkbox back to unchecked.
postgres_port_checkbox.setChecked(False)
# Now the checkbox should contain the port text, which has been set earlier.
assert port_line_edit.text() == port_text

View File

@@ -0,0 +1,172 @@
import unittest
import psycopg2
from pygadmin.connectionfactory import global_connection_factory
class TestConnectionFactoryMethods(unittest.TestCase):
"""
Test the methods and the functionality of the (global) connection factory.
"""
def test_factory_structure(self):
"""
Check the data structure of the factory: The factory should use a dict for saving the internal connection data.
"""
assert isinstance(global_connection_factory.connections_dictionary, dict)
def test_valid_get_connection(self):
"""
Use valid connection parameters for getting a correct connection.
"""
connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb", 5432, 10000)
assert isinstance(connection, psycopg2.extensions.connection)
def test_wrong_password_get_connection(self):
"""
Use a non existing user for testing a fail in the password storage, so the connection should be set to None.
"""
connection = global_connection_factory.get_database_connection("localhost", "test", "testdb")
assert connection is None
def test_invalid_get_connection(self):
"""
Use invalid connection parameters with an invalid/a non existing database, so the connection should be set to
False.
"""
connection = global_connection_factory.get_database_connection("localhost", "testuser", "test")
assert connection is False
def test_valid_get_parameters(self):
"""
Test the method for getting parameters based on a given database connection. Predefine a dictionary with
parameters, get the connection based on them and then, get the dictionary for the connection.
"""
# Define database connection parameters in a dictionary. The structure is equivalent to the structure of the
# dictionary, which is returned by the function of the factory for a connection.
database_parameters = {
"host": "localhost",
"user": "testuser",
"database": "testdb",
"port": 5432,
}
# Get a database connection.
connection = global_connection_factory.get_database_connection(database_parameters["host"],
database_parameters["user"],
database_parameters["database"],
database_parameters["port"])
# Get a dictionary based on the established connection.
factory_parameters = global_connection_factory.get_database_connection_parameters(connection)
# The dictionary, which was used to create a connection, and the dictionary, which matches with the connection,
# should be equivalent.
assert database_parameters == factory_parameters
def test_invalid_get_parameters(self):
"""
Test the method for getting connection parameters based on a connection with an invalid connection.
"""
# Use None as database connection, which is obviously not a valid database connection.
factory_parameter = global_connection_factory.get_database_connection_parameters(None)
# For an error case, the method should return None.
assert factory_parameter is None
def test_valid_connection_test(self):
"""
Use the method of the factory for testing a database connection with valid database connection parameters.
"""
# A password is required for testing. Because this is a pure test environment and the data is more or less
# random and the database is localhost, the password is hard coded and visible in this file.
connection_possible = global_connection_factory.test_parameters_for_database_connection("localhost", "testuser",
"testdb", "test1234")
# A correct connection should return True.
assert connection_possible is True
def test_invalid_connection_test(self):
"""
Use the method of the factory for testing a database connection with invalid database connection parameters.
"""
# Use invalid database connection parameters with an incorrect password.
connection_possible = global_connection_factory.test_parameters_for_database_connection("localhost", "testuser",
"test", "test42")
print(connection_possible)
# An invalid connection should return False.
assert connection_possible is False
def test_valid_close_connection(self):
"""
Test the correct close and delete mechanism for a database connection.
"""
# Get a database connection.
connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb")
# Close the connection and get the boolean for closing.
connection_closed = global_connection_factory.close_and_remove_database_connection(connection)
# Check the boolean for closing.
assert connection_closed is True
# Double check: Try to find the connection parameters, which are related to the database connection. They should
# be None for not found.
assert global_connection_factory.get_database_connection_parameters(connection) is None
def test_invalid_close_connection(self):
"""
Test the close and delete mechanism for an invalid database connection.
"""
# Try to close an invalid database connection.
connection_closed = global_connection_factory.close_and_remove_database_connection(None)
# The result should be not True.
assert connection_closed is not True
def test_connection_reestablish(self):
"""
Test the method for reestablishing a database connection.
"""
# Define database connection parameters for establishing a connection.
database_parameters = {
"host": "localhost",
"user": "testuser",
"database": "testdb",
"port": 5432,
}
# Get the first connection related to the given parameters.
connection = global_connection_factory.get_database_connection(database_parameters["host"],
database_parameters["user"],
database_parameters["database"],
database_parameters["port"])
# Use the database parameters for creating a new connection, which is the reestablished old connection.
new_connection = global_connection_factory.reestablish_terminated_connection(database_parameters)
# The old connection should be closed, so the closed attribute should be 1.
assert connection.closed == 1
# Try to get connection parameters related to the old connection. This should be None, because a match is not
# found.
assert global_connection_factory.get_database_connection_parameters(connection) is None
# The new connection should be open, so the attribute should be 0.
assert new_connection.closed == 0
# Check for the related connection parameters, which should be the initial dictionary.
assert global_connection_factory.get_database_connection_parameters(new_connection) == database_parameters

View File

@@ -0,0 +1,251 @@
import unittest
import os
from pygadmin.connectionstore import global_connection_store
class TestConnectionStoreMethods(unittest.TestCase):
"""
Test the connection store with its method and its behavior.
"""
def test_path_of_connection_file(self):
"""
Test the existence of the file for storing the connection parameters.
"""
assert os.path.exists(global_connection_store.yaml_connection_parameters_file)
def test_connection_list(self):
"""
Test the connection list for its correct instance, which is also an implicit test for its existence.
"""
assert isinstance(global_connection_store.connection_parameters_yaml, list)
def test_get_connection_parameters(self):
"""
Test the function for getting all connection parameters.
"""
# Use the function for getting the list.
connection_parameter_list = global_connection_store.get_connection_parameters_from_yaml_file()
# Check, if the returned list is the one, which contains all connection parameters in the connection store.
assert connection_parameter_list == global_connection_store.connection_parameters_yaml
def test_valid_save_connection_parameters(self):
"""
Test the function for saving connection parameters with valid paramters.
"""
# Define valid parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 5432}
# Save the parameters and assume a result, which is True.
assert global_connection_store.save_connection_parameters_in_yaml_file(test_parameters) is True
# Use a clean up with deleting the connection.
global_connection_store.delete_connection(test_parameters)
def test_invalid_save_connection_parameters(self):
"""
Test the function for saving connection parameters with invalid parameters.
"""
# Use an empty dictionary as invalid parameters.
assert global_connection_store.save_connection_parameters_in_yaml_file({}) is False
def test_duplicate_check(self):
"""
Test the function for a duplicate check.
"""
# Define test parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Save the parameters in the connection store and yaml file.
global_connection_store.save_connection_parameters_in_yaml_file(test_parameters)
# Use the function for checking a duplicate with the test parameters again.
assert global_connection_store.check_parameter_for_duplicate(test_parameters) is True
# Clean up.
global_connection_store.delete_connection(test_parameters)
def test_valid_delete_connection(self):
"""
Test the function for deleting a connection with saving parameters first and then deleting them.
"""
# Define test parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Save the parameters.
global_connection_store.save_connection_parameters_in_yaml_file(test_parameters)
# Delete the parameters and assume a successful deletion.
assert global_connection_store.delete_connection(test_parameters) is True
def test_invalid_delete_connection(self):
"""
Test the deletion of an invalid connection dictionary.
"""
# Use an empty dictionary as invalid dictionary.
assert global_connection_store.delete_connection({}) is False
def test_valid_change_connection(self):
"""
Test the change of a connection with a valid connection dictionary and a new dictionary with changed paramters.
"""
# Define the first test parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Save the first parameters.
global_connection_store.save_connection_parameters_in_yaml_file(test_parameters)
# Define changed parameters with a different port.
changed_test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 5432}
# Test for the correct change of parameters.
assert global_connection_store.change_connection(test_parameters, changed_test_parameters) is True
# Clean up.
global_connection_store.delete_connection(changed_test_parameters)
def test_invalid_change_connection(self):
"""
Test the function for changing information about a connection with invalid/duplicate data.
"""
# Define a dictionary with connection parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Save the connection.
global_connection_store.save_connection_parameters_in_yaml_file(test_parameters)
# Try to change the connection information, but this test should return False, because it is a duplicate.
assert global_connection_store.change_connection(test_parameters, test_parameters) is False
# Clean up.
global_connection_store.delete_connection(test_parameters)
def test_valid_check_key(self):
"""
Test the method for checking for the correct keys in the connection dictionary with valid data.
"""
# Define a dictionary with test parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Assume a success.
assert global_connection_store.check_for_correct_keys_in_dictionary(test_parameters) is True
def test_invalid_check_key(self):
"""
Test the method for checking for the correct keys in the dictionary with invalid data.
"""
# Use an empty dictionary as invalid data.
assert global_connection_store.check_for_correct_keys_in_dictionary({}) is False
def test_connection_parameter_number(self):
"""
Test the method for getting the number of connection parameters.
"""
# Get the length of the list with parameters and compare them with the result of the method.
assert len(global_connection_store.connection_parameters_yaml) \
== global_connection_store.get_number_of_connection_parameters()
def test_valid_index_of_connection(self):
"""
Test the method for getting the index of a connection with a known dictionary and valid data.
"""
# Get the current number of connection parameters before adding new data.
current_parameters_number = global_connection_store.get_number_of_connection_parameters()
# Define a test dictionary.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Save the test dictionary.
global_connection_store.save_connection_parameters_in_yaml_file(test_parameters)
# Check for the correct index of the new connection.
assert global_connection_store.get_index_of_connection(test_parameters) == current_parameters_number
# Clean up.
global_connection_store.delete_connection(test_parameters)
def test_invalid_index_of_connection(self):
"""
Test the method for getting the index of a connection with invalid data and as a result an invalid index.
"""
# Use an empty dictionary as invalid data.
assert global_connection_store.get_index_of_connection({}) is None
def test_valid_connection_at_index(self):
"""
Test the method for getting an index at a specified position.
"""
# Define test parameters.
test_parameters = {"Host": "testhost",
"Username": "testuser",
"Database": "testdb",
"Port": 1337}
# Save the parameters.
global_connection_store.save_connection_parameters_in_yaml_file(test_parameters)
# After a save of parameters, there has to be a connection at index 0.
connection_at_index = global_connection_store.get_connection_at_index(0)
# Check the connection for the right instance.
assert isinstance(connection_at_index, dict)
# Check the connection for the correct keys, so the data structure is correct.
assert "Host" in connection_at_index
assert "Username" in connection_at_index
assert "Database" in connection_at_index
assert "Port" in connection_at_index
# Clean up.
global_connection_store.delete_connection(test_parameters)
def test_invalid_connection_at_index(self):
"""
Test the method for getting a connection at a given index with invalid data.
"""
# Get the current number of connections.
current_connection_number = global_connection_store.get_number_of_connection_parameters()
# Check for the current number of connection as index (which is None, because the index starts at 0).
assert global_connection_store.get_connection_at_index(current_connection_number) is None

View File

@@ -0,0 +1,277 @@
import os
import re
import unittest
from pygadmin.database_dumper import DatabaseDumper
from pygadmin.configurator import global_app_configurator
class TestDatabaseDumperMethods(unittest.TestCase):
"""
Test the class for dumping a database and its behavior.
"""
def test_valid_database_dump(self):
"""
Use valid data for dumping a database and get the result.
"""
# Use a valid connection and valid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "Table", "test")
# Get the result of a database dump.
result = database_dumper.dump_database()
assert result is not None
def test_invalid_database_dump(self):
"""
Use invalid data for dumping a database and check the invalid result.
"""
# Use an invalid connection and invalid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 1337, "Table", "test")
# Get the result of a database dump.
result = database_dumper.dump_database()
assert result is None
def test_valid_create_pass_file(self):
"""
Test the method for creating a pass file with valid data.
"""
# Define the relevant data for a dump.
user = "testuser"
database = "testdb"
host = "localhost"
port = 5432
dump_information = "Table"
table_name = "test"
# Define a password identifier, which is relevant for the creating of a pass file.
password_identifier = "{}@{}:{}".format(user, host, port)
# Create a dumper.
database_dumper = DatabaseDumper(user, database, host, port, dump_information, table_name)
# Get the file path and handler.
file_path, file_handler = database_dumper.create_pass_file(password_identifier)
# Check the file path and the file handler for its existence.
assert os.path.exists(file_path) is True
assert os.path.exists(file_handler) is True
def test_invalid_create_pass_file(self):
"""
Test the creation and usage of a pass file with invalid data, so the host, user and port cannot be found in the
password manager. The file creation and usage should function normally.
"""
# Define the relevant data for a dump.
user = "testasdf"
database = "testdb"
host = "unknown"
port = 1337
dump_information = "Table"
table_name = "test"
# Define a password identifier, which is relevant for the creating of a pass file.
password_identifier = "{}@{}:{}".format(user, host, port)
# Create a dumper.
database_dumper = DatabaseDumper(user, database, host, port, dump_information, table_name)
# Get the file path and handler.
file_path, file_handler = database_dumper.create_pass_file(password_identifier)
# Check the file path and the file handler for its existence, because they should also exist for invalid data.
assert os.path.exists(file_path) is True
assert os.path.exists(file_handler) is True
def test_pg_dump_path(self):
"""
Test the functionality of the method for getting the pg dump path with also checking for the path in the global
app configurator.
"""
# Get the pg dump path out of the global app configurator.
configurator_dump_path = global_app_configurator.get_single_configuration("pg_dump_path")
# Create a dumper.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "Table", "test")
# Get the dump path as accessible attribute of the class.
database_dumper.get_pg_dump_path()
# If a path in the configurator does exist, check for the correct set.
if configurator_dump_path is not None and os.path.exists(configurator_dump_path):
# The path in the configurator should be the pg dump path of the dumper.
assert database_dumper.pg_dump_path == configurator_dump_path
# The path should not be a None, so it has been set.
assert database_dumper.pg_dump_path is not None
def test_database_pg_dump_statement(self):
"""
Test the creation of a pg dump statement for a database.
"""
# Define the relevant parameters as local variables.
user = "testuser"
database = "testdb"
host = "localhost"
port = 5432
dump_information = "Database"
information_name = "testdb"
# Create a dumper.
database_dumper = DatabaseDumper(user, database, host, port, dump_information, information_name)
# Get the dump path as attribute of the dumper, which is necessary for the dump statement.
database_dumper.get_pg_dump_path()
# Get the dump statement as attribute of the dumper.
database_dumper.get_pg_dump_statement()
# The statement is a list, so get the list.
statement_list = database_dumper.pg_dump_statement
# Check for the correct instance of the list.
assert isinstance(statement_list, list)
# Check for the relevant strings and statements as part of the statement list.
assert database_dumper.pg_dump_path in statement_list
assert "-T*" in statement_list
assert "--create" in statement_list
assert "--dbname=postgresql://{}@{}:{}/{}".format(user, host, port, database) in statement_list
def test_table_pg_dump_statement(self):
"""
Test the creation of a pg dump statement for a table.
"""
# Define the relevant parameters as local variables.
user = "testuser"
database = "testdb"
host = "localhost"
port = 5432
dump_information = "Table"
information_name = "test"
# Create a dumper.
database_dumper = DatabaseDumper(user, database, host, port, dump_information, information_name)
# Get the dump path as attribute of the dumper, which is necessary for the dump statement.
database_dumper.get_pg_dump_path()
# Get the dump statement as attribute of the dumper.
database_dumper.get_pg_dump_statement()
# The statement is a list, so get the list.
statement_list = database_dumper.pg_dump_statement
# Check for the correct instance of the list.
assert isinstance(statement_list, list)
# Check for the relevant strings and statements as part of the statement list.
assert database_dumper.pg_dump_path in statement_list
assert "--table={}".format(information_name) in statement_list
assert "--schema-only" in statement_list
assert "--dbname=postgresql://{}@{}:{}/{}".format(user, host, port, database) in statement_list
def test_valid_database_dump_clean_result(self):
"""
Test the dump of a database with valid data and test the clean of the result.
"""
# Use a valid connection and valid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "Table", "test")
# Get the result of a database dump.
result = database_dumper.dump_database_and_clean_result()
# The result should be a list.
assert isinstance(result, list)
def test_invalid_database_dump_clean_result(self):
"""
Test the dump of a database with invalid data and test the clean of the result.
"""
# Use an invalid connection and invalid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 1337, "Table", "test")
# Get the result of a database dump.
result = database_dumper.dump_database()
assert result is None
def test_clean_database_result(self):
"""
Test the clean of the database result.
"""
# Use a valid connection and valid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "Database", "testdb")
# Get the result of a database dump.
result = database_dumper.dump_database()
# Split the result into lines.
result_lines = result.stdout.split(os.linesep)
# Clean the result.
result_list = database_dumper.clean_database_result(result_lines)
# Check for the correct clean, so only lines with CREATE or ALTER are valid.
for line in result_list:
assert re.search("CREATE|ALTER", line) is not None
def test_clean_table_result(self):
"""
Test the clean of the table result.
"""
# Use a valid connection and valid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "Table", "test")
# Get the result of a database dump.
result = database_dumper.dump_database()
# Split the result into lines.
result_lines = result.stdout.split(os.linesep)
# Clean the table result.
result_list = database_dumper.clean_table_result(result_lines)
# Define a bracket count, which counts opened and closed brackets.
bracket_count = 0
# Check every line for a CREATE or open/closed brackets.
for line in result_list:
assert re.search("CREATE", line) or bracket_count != 0
for character in line:
if character == "(":
bracket_count += 1
if character == ")":
bracket_count -= 1
def test_clean_view_result(self):
"""
Test the clean of a view result.
"""
# Use a valid connection and valid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "View", "testview")
# Get the result of a database dump.
result = database_dumper.dump_database()
# Split the result into lines.
result_lines = result.stdout.split(os.linesep)
# Clean the table result
result_list = database_dumper.clean_view_result(result_lines)
# This line is set to True after a CREATE VIEW and is set to False after a semicolon, which ends the command.
create_view = False
# Check the result lines.
for line in result_list:
# The line should contain a CREATE VIEW or the create view should be in a previous line.
assert re.search("CREATE VIEW", line) or create_view is True
create_view = True
# Check for a semicolon to end the command.
for character in line:
if character == ";":
create_view = False
def test_invalid_clean_result(self):
# Use a valid connection and valid dump data.
database_dumper = DatabaseDumper("testuser", "testdb", "localhost", 5432, "Database", "testdb")
database_dumper.clean_database_result(None)

View File

@@ -0,0 +1,160 @@
import unittest
from pygadmin.database_query_executor import DatabaseQueryExecutor
from pygadmin.connectionfactory import global_connection_factory
class TestDatabaseQueryExecutorMethods(unittest.TestCase):
"""
Test the methods and the functionality of the database query executor.
"""
def test_creation(self):
"""
Test the creation of an object of the type database query executor.
"""
executor = DatabaseQueryExecutor()
# Check all relevant data as set to None.
assert executor.database_connection is None
assert executor.database_query is None
assert executor.database_query_parameter is None
def test_valid_execute_query(self):
"""
Test the execution of a database query with valid input parameters.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
# Create a database connection.
database_connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb")
# Get the result and the message of a query.
result_data_list, query_message = executor.execute_query("SELECT * FROM test;", database_connection.cursor())
# The first result should be a list.
assert isinstance(result_data_list, list)
# The second result should be a message as string.
assert isinstance(query_message, str)
def test_invalid_execute_query(self):
"""
Test the execution of a database query with invalid input parameters.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
# Create a database connection.
database_connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb")
# This try statement is used for causing an error and catching it, because with an invalid table, there will
# be an error. assertRaise cannot be used, because the resulting error is a psycopg2 error and not a python
# exception.
try:
# Execute a query with an invalid/a undefined table.
executor.execute_query("SELECT * FROM testtt;", database_connection.cursor())
# Assert something, which is wrong, so the test will fail, if this statement is reached.
assert 2 + 2 == 5
# Use the exception block for the assertion: Reaching this block, something, which is true, will be asserted, so
# the test will pass.
except Exception as error:
assert isinstance(error, Exception)
def test_valid_connection_with_valid_parameters(self):
"""
Test the method is_connection_valid of the database query executor with valid database connection parameters and
a valid database connection.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
# Create a database connection.
database_connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb")
# Set the new database connection as connection for the executor.
executor.database_connection = database_connection
# The fresh and new connection should be valid.
assert executor.is_connection_valid() is True
# Close the database connection.
database_connection.close()
# Now the connection after a close should be invalid.
assert executor.is_connection_valid() is False
# Clean up: Remove the connection from the connection factory to prevent the further usage of the connection,
# which can cause errors or test failures.
global_connection_factory.close_and_remove_database_connection(database_connection)
def test_valid_connection_with_invalid_parameters(self):
"""
Test the method is_connection_valid with invalid parameters and an invalid database connection.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
# Set the database connection of the executor to None.
executor.database_connection = None
# The connection should be invalid.
assert executor.is_connection_valid() is False
def test_reestablish_connection(self):
"""
Test the method for reestablishing a database connection.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
database_connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb")
# Set the new database connection as connection for the executor.
executor.database_connection = database_connection
# Check for a valid connection.
assert executor.is_connection_valid() is True
# Close the database connection.
database_connection.close()
# The connection should be invalid after a close.
assert executor.is_connection_valid() is False
# Reestablish the database connection.
executor.reestablish_connection()
# The connection should now be valid again.
assert executor.is_connection_valid() is True
def test_valid_connection_check_and_reestablish(self):
"""
Test the function check_for_valid_connection_and_reestablish of the executor with a valid database connection.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
database_connection = global_connection_factory.get_database_connection("localhost", "testuser", "testdb")
# Set the new database connection as connection for the executor.
executor.database_connection = database_connection
# The new connection should return True, because the connection is functional.
assert executor.check_for_valid_connection_and_reestablish() is True
# Close the database connection.
database_connection.close()
# Check for a valid connection and reestablish: This should be True, because a connection can be reestablished.
assert executor.check_for_valid_connection_and_reestablish() is True
def test_invalid_connection_check_and_reestablish(self):
"""
Test the function check_for_valid_connection_and_reestablish of the executor with an invalid database
connection.
"""
# Create an executor.
executor = DatabaseQueryExecutor()
# Set the database connection of the executor to None, which is an invalid database connection.
executor.database_connection = None
# The connection should be invalid. As a result, the connection cannot be reestablished.
assert executor.check_for_valid_connection_and_reestablish() is False

26
tests/test_dock.py Normal file
View File

@@ -0,0 +1,26 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.dock import DockWidget
from pygadmin.widgets.tree import TreeWidget
class TestDockWidgetMethods(unittest.TestCase):
"""
Test the basic functionality of the dock widget.
"""
def test_initial_attributes(self):
"""
Test the initial attributes of the dock.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create a dock widget.
dock_widget = DockWidget()
# The tree of the dock widget should be a TreeWidget
assert isinstance(dock_widget.tree, TreeWidget)

279
tests/test_editor.py Normal file
View File

@@ -0,0 +1,279 @@
import os
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.editor import EditorWidget
from pygadmin.models.tablemodel import TableModel
from pygadmin.database_query_executor import DatabaseQueryExecutor
from pygadmin.connectionfactory import global_connection_factory
class TestEditorWidgetMethods(unittest.TestCase):
"""
Test the functionality and methods of the editor widget.
"""
def test_initial_attributes(self):
"""
Check for the correct existence and instance of the initial attributes of the editor.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# Test for the correct instance of the table model.
assert isinstance(editor_widget.table_model, TableModel)
# The data list of the table model should be empty at the start.
assert editor_widget.table_model.data_list == []
# The current database connection should be None at the start.
assert editor_widget.current_database_connection is None
# The connection identifier should be None at at the start.
assert editor_widget.connection_identifier is None
# Test for the correct instance of the database query executor.
assert isinstance(editor_widget.database_query_executor, DatabaseQueryExecutor)
def test_valid_set_connection_based_on_parameters(self):
"""
Test the method for setting connection parameters based on parameters in a dictionary with valid connection
parameters.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# Define a connection parameter dictionary.
connection_dictionary = {"host": "localhost",
"database": "postgres",
"port": 5432,
"user": "testuser"}
# Get a database connection related to the parameters in the connection dictionary.
database_connection = global_connection_factory.get_database_connection(connection_dictionary["host"],
connection_dictionary["user"],
connection_dictionary["database"],
connection_dictionary["port"])
# Set the database connection of the editor based on the connection dictionary.
editor_widget.set_connection_based_on_parameters(connection_dictionary)
# After a successful set of a database connection, the data list of the table model should still be empty and
# without an error message.
assert editor_widget.table_model.data_list == []
# The database connection of the editor should be the connection based on the connection dictionary.
assert editor_widget.current_database_connection == database_connection
def test_invalid_set_connection_based_on_parameters(self):
"""
Test the method for setting connection parameters based on parameters in a dictionary with invalid connection
parameters.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# Define a connection parameter dictionary. The host parameter is an invalid parameter.
connection_dictionary = {"host": "localhorst",
"database": "postgres",
"port": 5432,
"user": "testuser"}
# Try to set the connection with the function for setting a database connection.
editor_widget.set_connection_based_on_parameters(connection_dictionary)
# After a failed set of a database connection, there should be a warning in the table model.
assert editor_widget.table_model.data_list != []
# The current database connection should be None after this kind of failure.
assert editor_widget.current_database_connection is None
def test_refresh_table_model(self):
"""
Test the method for refreshing the table model of the editor.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# Define a list with new data.
new_data_list = [["column 1, column 2"], (1, "row A", "row B"), (2, "row C", "row D")]
# Use the function for refreshing the data list of the table model.
editor_widget.refresh_table_model(new_data_list)
# The data list of the table model should be the new data list.
assert editor_widget.table_model.data_list == new_data_list
def test_save_current_statement_in_file(self):
"""
Test the function for saving the current statement in a file. User input is not necessary, because the file for
saving is predefined.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# Define a test text.
test_text = "This is a text for testing."
# Set the text as text of the query input editor for saving.
editor_widget.query_input_editor.setText(test_text)
# Define a test path.
test_path = os.path.join(os.path.expanduser("~"), '.pygadmin_test')
# Create the test path.
os.mkdir(test_path)
# Define a test file.
test_file = os.path.join(test_path, "test_file.txt")
# Use the test file as file for saving in the editor.
editor_widget.corresponding_saved_file = test_file
# Save the current statement and text of the query input editor in the pre defined test file.
editor_widget.save_current_statement_in_file()
# Open the test file.
with open(test_file, "r") as test_file:
# Get the text of the file, which should be the currently saved text.
saved_editor_text = test_file.read()
# Remove the file and the path as a clean up.
os.remove(test_file.name)
os.rmdir(test_path)
# Check the text: The inserted text in the editor should be the text, which is saved in the file.
assert test_text == saved_editor_text
def test_is_editor_empty(self):
"""
Test the method for an editor check: Is the editor empty or not?
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# After creating the widget, it should be empty.
assert editor_widget.is_editor_empty() is True
# Set a text to the editor, so it is not empty anymore.
editor_widget.query_input_editor.setText("Test Text")
# The method should now return False.
assert editor_widget.is_editor_empty() is False
# Set also an title to the editor widget.
editor_widget.setWindowTitle("Test Title")
# The method should still return False, because the editor is not empty.
assert editor_widget.is_editor_empty() is False
# Set the text of the editor back to an empty string.
editor_widget.query_input_editor.setText("")
# Set the text to a string with content.
editor_widget.setWindowTitle("Test Title")
# The editor widget should not be empty.
assert editor_widget.is_editor_empty() is False
def test_get_connection_status_string_for_window_title(self):
"""
Test the method for determining the connection part of the window title based on the different kinds of
connections and their validity.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# After the creation of the editor widget, the connection status string should be an empty string.
assert editor_widget.get_connection_status_string_for_window_title() == ""
# Set the database connection of the editor to False for simulating a failed database connection.
editor_widget.current_database_connection = False
# Now there should be an alert to a failed connection.
assert editor_widget.get_connection_status_string_for_window_title() == "Connection failed: None"
# Simulate a valid database connection with setting it to True.
editor_widget.current_database_connection = True
# Define an identifier for the connection simulation.
test_identifier = "Test identifier"
# Set the test identifier as connection identifier of the editor.
editor_widget.connection_identifier = test_identifier
# The connection string for the window title should be the connection identifier for a valid database
# connection.
assert editor_widget.get_connection_status_string_for_window_title() == test_identifier
def test_get_corresponding_file_name_string_for_window_title_and_description(self):
"""
Test the method for getting the name of the file save path for the editor to set the correct window title.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# After the creation and without a corresponding saved file, the method should return a tuple of empty strings.
assert editor_widget.get_corresponding_file_name_string_for_window_title_and_description() == ("", "")
# Define a path for the test save file.
save_file_path = "test/testfile/"
# Define a name for the test save file.
save_file_name = "test.sql"
# Create a full path with path and name together.
full_save_file_path = "{}{}".format(save_file_path, save_file_name)
# Set the full path as corresponding saved file for simulating the behavior of a QFileDialog.
editor_widget.corresponding_saved_file = full_save_file_path
# Now the output should be the name of the file and the full path.
assert editor_widget.get_corresponding_file_name_string_for_window_title_and_description() == (
save_file_name, full_save_file_path)
def test_get_file_save_status_string_for_window_title(self):
"""
Test the method for checking the current status of the text in the query input editor of the editor compared to
its last saved version.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# The text in the editor should empty, so there should not be a change. The file save string should be empty.
assert editor_widget.get_file_save_status_string_for_window_title() == ""
# Set a text to the editor, so the initial text has changed.
editor_widget.query_input_editor.setText("Test text")
# After the text change, there should be the information about it in the file save string.
assert editor_widget.get_file_save_status_string_for_window_title() == " (*)"
def test_get_query_in_input_editor(self):
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget.
editor_widget = EditorWidget()
# Define a start text for testing, so this text can be chosen for a plain and simple selection later.
test_text_start = "Test"
# Define an end text for testing.
test_text_end = " Text"
# Put the two strings together as test text.
test_text = "{}{}".format(test_text_start, test_text_end)
# Set the test text as text of the query input editor.
editor_widget.query_input_editor.setText(test_text)
# The query in the query input editor should be the test text.
assert editor_widget.get_query_in_input_editor() == test_text
# Set the selection to the test text start.
editor_widget.query_input_editor.setSelection(0, 0, 0, len(test_text_start))
# Now the function for getting the query should return the test text start.
assert editor_widget.get_query_in_input_editor() == test_text_start

View File

@@ -0,0 +1,110 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.editor_appearance_settings import EditorAppearanceSettingsDialog
from pygadmin.configurator import global_app_configurator
class TestEditorAppearanceSettingsDialogMethods(unittest.TestCase):
"""
Test the functionality and methods of the editor appearance settings dialog.
"""
def test_initial_attributes(self):
"""
Test the existence and correct instance of some initial attributes.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an editor appearance settings dialog.
settings_dialog = EditorAppearanceSettingsDialog()
# Check for the dictionary with the GUI items.
assert isinstance(settings_dialog.color_items_dictionary, dict)
# Check for the dictionary with the currently existing color themes.
assert isinstance(settings_dialog.current_color_themes_dictionary, dict)
def test_set_selected_item_in_list_widget(self):
"""
Test the method for selecting a theme with the given name.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an editor appearance settings dialog.
settings_dialog = EditorAppearanceSettingsDialog()
# The theme "Hack" should be available as hard coded theme in the global app configurator.
item_to_select = "Hack"
# Select the item in the settings dialog.
settings_dialog.set_selected_item_in_list_widget(item_to_select)
# Get the selected item out of the list of selected items.
selected_item = settings_dialog.current_themes_list_widget.selectedItems()[0]
# The item to selected and the text of the selected item should be the same.
assert item_to_select == selected_item.text()
def test_get_selected_item_in_list_widget(self):
"""
Test the function for getting the selected item of the list widget as attribute of the dialog.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an editor appearance settings dialog.
settings_dialog = EditorAppearanceSettingsDialog()
# Clear the selection of the settings dialog. If there is a default theme, the default theme is selected.
settings_dialog.current_themes_list_widget.selectionModel().clearSelection()
# After clearing the selection, the method for getting the selected item should return False, because there is
# no selected item.
assert settings_dialog.get_selected_item_in_list_widget() is False
# The selected list widget item should be None, because there is no selection.
assert settings_dialog.selected_list_widget_item is None
# Choose an item for selecting.
item_to_select = "Hack"
# Set the selected item in the list widget.
settings_dialog.set_selected_item_in_list_widget(item_to_select)
# Now there should be a selected item in the list widget, so the function returns True.
assert settings_dialog.get_selected_item_in_list_widget() is True
# The selected item in the list widget should be the item to select.
assert settings_dialog.selected_list_widget_item == item_to_select
def test_save_changes_in_configuration_and_apply(self):
"""
Test the function for changing the current saves.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an editor appearance settings dialog.
settings_dialog = EditorAppearanceSettingsDialog()
# The function should return True for a successful save.
assert settings_dialog.save_changes_in_configuration_and_apply() is True
def test_set_default_theme(self):
"""
Test the method for setting a new default theme.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an editor appearance settings dialog.
settings_dialog = EditorAppearanceSettingsDialog()
# Choose an item for selecting.
item_to_select = "Hack"
# Set the selected item in the list widget.
settings_dialog.set_selected_item_in_list_widget(item_to_select)
# Set the default theme. The selected theme is now the default theme.
settings_dialog.set_default_theme()
# The default theme in the settings dialog should be saved in the global app configurator.
assert settings_dialog.default_theme == global_app_configurator.get_single_configuration("color_theme")

73
tests/test_lexer.py Normal file
View File

@@ -0,0 +1,73 @@
import unittest
from PyQt5.QtGui import QColor
from pygadmin.models.lexer import SQLLexer
class TestLexerMethods(unittest.TestCase):
"""
Use a class for testing the SQLLexer and its methods.
"""
def test_lexer_color_parameters_dictionary(self):
"""
Check the color parameter dictionary of the lexer, which should be not empty.
"""
lexer = SQLLexer(None)
assert lexer.color_parameters_dictionary != {}
def test_qcolor_lexer(self):
"""
Check the correct instance of the color in the color parameter dictionary of the lexer.
"""
lexer = SQLLexer(None)
for value in lexer.color_parameters_dictionary.values():
assert isinstance(value, QColor)
def test_correct_color_parameter_keys(self):
"""
Check for the right keys in the color parameter dictionary of the lexer.
"""
lexer = SQLLexer(None)
# Define the relevant color keys.
color_keys = ["default_color", "default_paper_color", "keyword_color", "number_color", "other_keyword_color",
"apostrophe_color"]
# Check every necessary key for its existence.
for color in color_keys:
assert lexer.color_parameters_dictionary[color]
def test_set_color(self):
"""
Test the method of the lexer for setting a color defined by a color dictionary with the color keyword and a
QColor for testing the color set.
"""
lexer = SQLLexer(None)
# Define a color dictionary with tests.
color_dictionary = {"default_color": QColor("ff0000ff"),
"default_paper_color": QColor("#ffffff00"),
"keyword_color": QColor("#ff00000f"),
"number_color": QColor("#ff000f0f"),
"other_keyword_color": QColor("#ff0f0f00"),
"apostrophe_color": QColor("#ff0f0000")
}
# Set the colors in the lexer.
lexer.set_lexer_colors(color_dictionary)
# Check, if every color has been set properly.
assert color_dictionary["default_color"].name() == lexer.defaultColor(10).name()
assert color_dictionary["default_paper_color"].name() == lexer.defaultPaper(0).name()
assert color_dictionary["default_paper_color"].name() == lexer.color(0).name()
assert color_dictionary["keyword_color"].name() == lexer.color(5).name()
assert color_dictionary["number_color"].name() == lexer.color(4).name()
assert color_dictionary["other_keyword_color"].name() == lexer.color(8).name()
assert color_dictionary["apostrophe_color"].name() == lexer.color(7).name()

206
tests/test_main_window.py Normal file
View File

@@ -0,0 +1,206 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication, QMdiArea, QDockWidget, QMenuBar, QToolBar
from pygadmin.widgets.main_window import MainWindow
from pygadmin.widgets.connection_dialog import ConnectionDialogWidget
from pygadmin.widgets.configuration_settings import ConfigurationSettingsDialog
from pygadmin.widgets.editor_appearance_settings import EditorAppearanceSettingsDialog
from pygadmin.widgets.version_information_dialog import VersionInformationDialog
from pygadmin.configurator import global_app_configurator
class TestMainWindowMethods(unittest.TestCase):
"""
Test the functionality and methods of the main window.
"""
@staticmethod
def set_opening_connection_dialog_to_false():
"""
Set the configuration for opening a connection dialog at the start of the application/main window to False, so
a connection dialog is not displayed.
"""
global_app_configurator.set_single_configuration("open_connection_dialog_at_start", False)
def test_initial_attributes(self):
"""
Test the existence and correct instance of some initial attributes.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# The MdiArea of the main window should be a QMdiArea.
assert isinstance(main_window.mdi_area, QMdiArea)
# The central widget should be the mdi area.
assert main_window.centralWidget() == main_window.mdi_area
# The sub window list of the mdi area should contain one item, because there is one editor at the start.
assert len(main_window.mdi_area.subWindowList()) == 1
# The dock widget should be a QDockWidget.
assert isinstance(main_window.dock_widget, QDockWidget)
# The menu bar should be a QMenuBar.
assert isinstance(main_window.menu_bar, QMenuBar)
# The tool bar should be a QToolBar.
assert isinstance(main_window.tool_bar, QToolBar)
# The status bar should show the message "Ready" at the start.
assert main_window.statusBar().currentMessage() == "Ready"
def test_add_action_to_menu_bar(self):
"""
Test the correct appending of an action to the menu bar. In this case, the edit menu point is used.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Define a name for the new action.
new_action_name = "test"
# The name of the new action should not be the name of an existing action.
for action in main_window.edit_menu.actions():
assert action.text() != new_action_name
# Add the action with the new name and a simple test function to the menu bar. Without a menu, the edit menu is
# used.
main_window.add_action_to_menu_bar(new_action_name, lambda: print("test"))
# Check for an action with the name of the new action. The result should be one item, because there is one item
# with the name of the new action: The new action.
matching_action = [action.text() for action in main_window.edit_menu.actions()
if action.text() == new_action_name]
# The list should contain one element.
assert len(matching_action) == 1
def test_add_action_to_tool_bar(self):
"""
Test the correct appending of an action to the tool bar.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Define a name for the new action.
new_action_name = "test"
# The name of the new action should be unique, so there should not be an action with its text/name.
for action in main_window.tool_bar.actions():
assert new_action_name != action.text()
# Add the new action to the tool bar. The path for the icon is an invalid test path and the function is only a
# simple test function.
main_window.add_action_to_tool_bar(new_action_name, "test_path", lambda: print("test"))
# Check for an action with the name of the new action. The result should be one item, because there is one item
# with the name of the new action: The new action.
matching_action = [action.text() for action in main_window.tool_bar.actions()
if action.text() == new_action_name]
# The resulting list should contain one element.
assert len(matching_action) == 1
def test_activate_new_connection_dialog(self):
"""
Test the activation of a new connection dialog.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Activate a new connection dialog.
main_window.activate_new_connection_dialog()
# The new connection dialog should be a connection dialog.
assert isinstance(main_window.new_connection_dialog, ConnectionDialogWidget)
# The new connection dialog should be visible, because it is active.
assert main_window.new_connection_dialog.isVisible() is True
def test_activate_new_configuration_settings_dialog(self):
"""
Test the activation of a new configuration settings dialog.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Activate a new configuration settings dialog.
main_window.activate_new_configuration_settings_dialog()
# The new dialog should have the correct type.
assert isinstance(main_window.configuration_settings_dialog, ConfigurationSettingsDialog)
# The dialog should be visible/active.
assert main_window.configuration_settings_dialog.isVisible() is True
def test_activate_new_editor_appearance_dialog(self):
""""
Test the activation of a new editor appearance dialog.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Activate a new editor appearance settings dialog.
main_window.activate_new_editor_appearance_dialog()
# The new dialog should have the correct type.
assert isinstance(main_window.editor_appearance_dialog, EditorAppearanceSettingsDialog)
# The dialog should be visible/active.
assert main_window.editor_appearance_dialog.isVisible() is True
def test_show_status_bar_message(self):
"""
Test the function for showing a new status bar message.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Define a new message for the status bar.
new_message = "test"
# Set the message in the status bar.
main_window.show_status_bar_message(new_message)
# The status bar message should be the new message.
assert main_window.statusBar().currentMessage() == new_message
def test_show_version_information_dialog(self):
""""
Test the activation of a new version information dialog.
"""
self.set_opening_connection_dialog_to_false()
# Create an app, because this is necessary for testing a QMainWindow.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Show a new version information dialog.
main_window.show_version_information_dialog()
# The new dialog should have the correct type.
assert isinstance(main_window.version_information_dialog, VersionInformationDialog)
# The dialog should be visible/active.
assert main_window.version_information_dialog.isVisible() is True

167
tests/test_mdi_area.py Normal file
View File

@@ -0,0 +1,167 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.mdi_area import MdiArea
from pygadmin.widgets.editor import EditorWidget
from pygadmin.connectionfactory import global_connection_factory
class TestMdiAreaMethods(unittest.TestCase):
"""
Test the functionality and methods of Mdi area.
"""
def test_initial_attributes(self):
"""
Test the existence and correct instance of some initial attributes.
"""
# Create an app, because this is necessary for testing a QMdiArea.
app = QApplication(sys.argv)
# Create an MdiArea.
mdi_area = MdiArea()
# The tabs in the MdiArea should be movable.
assert mdi_area.tabsMovable() is True
# The tabs in the MdiArea should be closable.
assert mdi_area.tabsClosable() is True
# The view mode should be 1, which is the tab view.
assert mdi_area.viewMode() == 1
def test_generate_editor_widget(self):
"""
Test the correct generating process of an editor in the MdiArea.
"""
# Create an app, because this is necessary for testing a QMdiArea.
app = QApplication(sys.argv)
# Create an MdiArea.
mdi_area = MdiArea()
# Generate an editor, which is also the return value of the function.
generated_editor = mdi_area.generate_editor_tab()
# The generated editor should be an editor widget.
assert isinstance(generated_editor, EditorWidget)
# Get the widgets of the sub windows of the MdiArea as list.
widget_list = [sub_window.widget() for sub_window in mdi_area.subWindowList()]
# The generated editor should be in the widget list.
assert generated_editor in widget_list
def test_change_current_sub_window_and_connection_parameters(self):
"""
Test the method for setting new database connection parameters in case of an editor change in the MdiArea.
"""
# Create an app, because this is necessary for testing a QMdiArea.
app = QApplication(sys.argv)
# Create an MdiArea.
mdi_area = MdiArea()
# Generate an editor, so there is a current sub window.
generated_editor = mdi_area.generate_editor_tab()
# Define a dictionary with connection parameters.
connection_parameters = {"host": "localhost",
"user": "testuser",
"database": "testdb",
"port": 5432}
# Set the connection parameters.
mdi_area.change_current_sub_window_and_connection_parameters(connection_parameters)
# Get the current connection of the editor.
editor_connection = generated_editor.current_database_connection
# Get the connection dictionary related to the connection of the editor.
editor_connection_parameters = global_connection_factory.get_database_connection_parameters(editor_connection)
# The connection parameters of the editor should be identical to the initial connection parameters.
assert editor_connection_parameters == connection_parameters
def test_determine_current_editor_widget(self):
"""
Test the method for determining the current editor widget.
"""
# Create an app, because this is necessary for testing a QMdiArea.
app = QApplication(sys.argv)
# Create an MdiArea.
mdi_area = MdiArea()
# Right after the initialization and without any editor widget, the function for determining the current editor
# widget should return None.
assert mdi_area.determine_current_editor_widget() is None
# Generate a new editor tab.
generated_editor = mdi_area.generate_editor_tab()
# The current editor widget should be the freshly generated editor.
assert mdi_area.determine_current_editor_widget() == generated_editor
def test_determine_empty_editor_widget_with_connection(self):
"""
Test the method for getting an empty editor widget with a given database connection.
"""
# Create an app, because this is necessary for testing a QMdiArea.
app = QApplication(sys.argv)
# Create an MdiArea.
mdi_area = MdiArea()
# Generate a new editor tab.
editor_widget = mdi_area.generate_editor_tab()
# Define a dictionary with connection parameters for the freshly generated editor widget.
first_connection_parameters = {"host": "localhost",
"user": "testuser",
"database": "testdb",
"port": 5432}
# Get a connection based on the dictionary with connection parameters.
connection = global_connection_factory.get_database_connection(first_connection_parameters["host"],
first_connection_parameters["user"],
first_connection_parameters["database"],
first_connection_parameters["port"])
# Set the new connection as current connection of the generated editor widget.
editor_widget.current_database_connection = connection
# The editor with the database connection should be the generated editor_widget.
assert mdi_area.determine_empty_editor_widget_with_connection(first_connection_parameters) == editor_widget
# Define a second dictionary with different connection parameters.
second_connection_parameters = {"host": "localhost",
"user": "testuser",
"database": "postgres",
"port": 5432}
# A new generated widget with new connection parameters should not be the first generated editor widget.
assert mdi_area.determine_empty_editor_widget_with_connection(second_connection_parameters) != editor_widget
def test_determine_next_empty_editor_widget(self):
"""
Test the method for determining the next empty editor widget.
"""
# Create an app, because this is necessary for testing a QMdiArea.
app = QApplication(sys.argv)
# Create an MdiArea.
mdi_area = MdiArea()
# After the initialization and without any editor widgets, the function should return None,
assert mdi_area.determine_next_empty_editor_widget() is None
# Generate an editor widget.
first_editor_widget = mdi_area.generate_editor_tab()
# The generated widget should be an empty editor widget.
assert mdi_area.determine_next_empty_editor_widget() == first_editor_widget
# Set a text to the editor widget, so it is not empty anymore.
first_editor_widget.query_input_editor.setText("Not Empty")
# There is only one widget and this widget is not empty, so the function for determining an empty editor widget
# should return None.
assert mdi_area.determine_next_empty_editor_widget() is None
# Generate a new editor tab.
second_editor_widget = mdi_area.generate_editor_tab()
# The freshly generated widget should be the next empty editor widget.
assert mdi_area.determine_next_empty_editor_widget() == second_editor_widget

View File

@@ -0,0 +1,125 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.node_create_information import NodeCreateInformationDialog
from pygadmin.models.treemodel import DatabaseNode, TableNode, ViewNode
class TestNodeCreateInformationMethods(unittest.TestCase):
"""
Test the functionality and methods of node create information dialog.
"""
def test_dialog_without_node(self):
"""
Test the reaction of the dialog to the input of None instead of a node.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an information dialog without a node.
node_information_dialog = NodeCreateInformationDialog(None)
# The window title should assume an error.
assert node_information_dialog.windowTitle() == "Node Input Error"
def test_dialog_with_valid_database_node(self):
"""
Test the node information dialog with a database node.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a database node for the dialog.
database_node = DatabaseNode("testdb", "localhost", "testuser", "testdb", 5432, 10000)
# Create an information dialog with the database node.
node_information_dialog = NodeCreateInformationDialog(database_node)
# The selected node should be the database node.
assert node_information_dialog.selected_node == database_node
# Get the create statement of the node.
create_statement = node_information_dialog.get_node_create_statement()
self.check_create_statement(create_statement)
def test_dialog_with_valid_table_node(self):
"""
Test the node information dialog with a table node.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a table node for the dialog.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Create an information dialog with the table node.
node_information_dialog = NodeCreateInformationDialog(table_node)
# The selected node should be the table node.
assert node_information_dialog.selected_node == table_node
# Get the create statement of the node.
create_statement = node_information_dialog.get_node_create_statement()
self.check_create_statement(create_statement)
def test_dialog_with_valid_view_node(self):
"""
Test the node information dialog with a view node.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a view node for the dialog.
view_node = ViewNode("testview", "localhost", "testuser", "testdb", 5432, 10000)
# Create an information dialog with view node.
node_information_dialog = NodeCreateInformationDialog(view_node)
# The selected node should be the view node.
assert node_information_dialog.selected_node == view_node
# Get the create statement of the node.
create_statement = node_information_dialog.get_node_create_statement()
self.check_create_statement(create_statement)
def test_dialog_with_invalid_node(self):
"""
Test the dialog with an invalid database node as error case.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a database node with invalid connection parameters. In this case, the port is invalid.
database_node = DatabaseNode("testdb", "localhost", "testuser", "testdb", 1337, 10000)
node_information_dialog = NodeCreateInformationDialog(database_node)
# The selected node should be the database node.
assert node_information_dialog.selected_node == database_node
# Get the create statement of the node.
create_statement = node_information_dialog.get_node_create_statement()
self.check_create_statement(create_statement)
@staticmethod
def check_create_statement(create_statement):
"""
Define a method for checking the create statement of a node. The statement should contain at least one specified
word in a list.
"""
# The create statement should not be empty.
assert create_statement != ""
# Define a list with possible sub strings for a create statement. The string "failed" is in the list for the
# error case.
statement_can_contain_list = ["\nWITH", "\nENCODING", "\nLC_COLLATE", "\nLC_CTYPE", "\nLC_TYPE", "\nALTER",
"CREATE", "failed"]
# Define a boolean for checking the existence of a word in the list. This boolean is used in the for loop and
# after the loop, it should be True.
contains_string = False
# Check for the existence of at least one word of the list.
for possible_string in statement_can_contain_list:
# Check for the string, which could be part of the create statement.
if possible_string in create_statement:
# Change the check boolean to True.
contains_string = True
# After iterating over the list with words, the boolean for checking should be True.
assert contains_string is True

View File

@@ -0,0 +1,32 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.permission_information import PermissionInformationDialog
from pygadmin.models.treemodel import DatabaseNode, TableNode
class TestPermissionInformationMethods(unittest.TestCase):
"""
Test the functionality and methods of node create information dialog.
"""
def test_dialog_without_node(self):
"""
Test the reaction of the dialog to the input of None instead of a node.
"""
app = QApplication(sys.argv)
permission_information_dialog = PermissionInformationDialog(None)
assert permission_information_dialog.windowTitle() == "Node Input Error"
def test_dialog_with_node(self):
"""
Test the dialog with an existing node.
"""
app = QApplication(sys.argv)
database_node = DatabaseNode("testdb", "localhost", "testuser", "testdb", 5432, 10000)
permission_information_dialog = PermissionInformationDialog(database_node)
assert permission_information_dialog.selected_node == database_node

View File

@@ -0,0 +1,109 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.editor import EditorWidget
from pygadmin.widgets.search_replace_widget import SearchReplaceWidget
class TestSearchPlaceWidgetMethods(unittest.TestCase):
"""
Test the functionality and methods of the search replace widget.
"""
def test_initial_attributes(self):
"""
Check for the correct existence and instance of the initial attributes of the search replace widget.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget as parent for the search replace dialog.
editor_widget = EditorWidget()
# Create a search replace dialog with the editor widget as a parent
search_replace_widget = SearchReplaceWidget(editor_widget)
# The dictionaries with the search and replace items should exist as dictionaries.
assert isinstance(search_replace_widget.search_items, dict)
assert isinstance(search_replace_widget.replace_items, dict)
def test_hide_replace_components(self):
"""
Test the functionality of the method for hiding the replace components.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget as parent for the search replace dialog.
editor_widget = EditorWidget()
# Create a search replace dialog with the editor widget as a parent
search_replace_widget = SearchReplaceWidget(editor_widget)
# Hide the replace components.
search_replace_widget.hide_replace_components()
# Check every component for hiding.
for replace_item in search_replace_widget.replace_items.values():
# The replace item should not be visible.
assert replace_item.isVisible() is False
def test_show_replace_components(self):
"""
Test the method for showing the replace components.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget as parent for the search replace dialog.
editor_widget = EditorWidget()
# Create a search replace dialog with the editor widget as a parent
search_replace_widget = SearchReplaceWidget(editor_widget)
# Show the replace components.
search_replace_widget.show_replace_components()
# Check every component for showing.
for replace_item in search_replace_widget.replace_items.values():
# The replace item should be visible.
assert replace_item.isVisible() is True
def test_set_search_text(self):
"""
Test the method for setting the text of the search line edit.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget as parent for the search replace dialog.
editor_widget = EditorWidget()
# Create a search replace dialog with the editor widget as a parent
search_replace_widget = SearchReplaceWidget(editor_widget)
# Define a text for testing.
test_text = "Test"
# Set the test text.
search_replace_widget.set_search_text(test_text)
# The test text should be the text of the line edit.
assert search_replace_widget.search_items["search_line_edit"].text() == test_text
def test_get_search_and_replace_text(self):
"""
Test the method for getting the current text of the search and the replace line edit.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create an editor widget as parent for the search replace dialog.
editor_widget = EditorWidget()
# Create a search replace dialog with the editor widget as a parent
search_replace_widget = SearchReplaceWidget(editor_widget)
# Define a text for testing.
test_text = "Test"
# Set the text for testing as text of the search line edit.
search_replace_widget.search_items["search_line_edit"].setText(test_text)
# Now the method for getting the search text should return the test text.
assert search_replace_widget.get_search_text() == test_text
# Set the text for testing as text of the replace line edit.
search_replace_widget.replace_items["replace_line_edit"].setText(test_text)
# Now the method for getting the replace text should return the test text.
assert search_replace_widget.get_replace_text() == test_text

47
tests/test_start.py Normal file
View File

@@ -0,0 +1,47 @@
import unittest
import signal
import sys
import faulthandler
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.main_window import MainWindow
faulthandler.enable()
class TestStartMethods(unittest.TestCase):
"""
Test the correct start of the application.
"""
def test_start(self):
"""
Simulate the start of the application like in the main function in __init__.py, but without app.exec(), so a
user does not have to end the application manually.
"""
# Define easier ending of the application.
signal.signal(signal.SIGINT, signal.SIG_DFL)
# Define an app.
app = QApplication(sys.argv)
# Create a main window.
main_window = MainWindow()
# Show the main window, but the application just ends.
main_window.show()
def test_start_multiple_times(self):
"""
Simulate the start multiple times.
"""
for i in range(500):
print("Start test {}".format(i))
self.test_start()
print("Still alive")
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,102 @@
import sys
import unittest
from PyQt5.QtCore import QBasicTimer
from PyQt5.QtWidgets import QApplication, QProgressBar, QLabel
from pygadmin.widgets.start_progress_dialog import StartProgressDialog
from pygadmin.connectionstore import global_connection_store
class TestStartProgressDialogMethods(unittest.TestCase):
"""
Test the functionality and behavior of the start progress dialog.
"""
def test_initial_attributes(self):
"""
Test the initial attributes of the dialog.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a start progress dialog.
start_progress_dialog = StartProgressDialog()
# There should be a progress bar, because this is the whole idea of having a start progress dialog.
assert isinstance(start_progress_dialog.progress_bar, QProgressBar)
# There should also be a description label, informing about the current process.
assert isinstance(start_progress_dialog.description_label, QLabel)
# A timer is required for the functionality of the progress bar.
assert isinstance(start_progress_dialog.timer, QBasicTimer)
# The step at the beginning should be 0.
assert start_progress_dialog.float_step == 0
def test_progress_bar_with_zero_connections(self):
"""
Test the functionality of the progress bar without connections in the connection store.
"""
# Make a copy of the current connection list for storing it.
connection_list = global_connection_store.get_connection_parameters_from_yaml_file()
# Set the current list to an empty list.
global_connection_store.connection_parameters_yaml = []
# Delete all connections and store the empty list.
global_connection_store.commit_current_list_to_yaml()
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a start progress dialog.
start_progress_dialog = StartProgressDialog()
# Start the progress bar without connections.
start_progress_dialog.start_progress_bar()
# Now the float step and the step size should be 100.
assert start_progress_dialog.float_step == 100
assert start_progress_dialog.step_size == 100
# Restore the connection list.
global_connection_store.connection_parameters_yaml = connection_list
global_connection_store.commit_current_list_to_yaml()
def test_progress_bar_with_connections(self):
"""
Test the progress bar with existing connections.
"""
# Define one dictionary for one connection.
first_connection_dictionary = {"Host": "testhost",
"Username": "testuser",
"Database": "postgres",
"Port": 5432}
# Define another dictionary for a second connection.
second_connection_dictionary = {"Host": "anothertesthost",
"Username": "testuser",
"Database": "postgres",
"Port": 5432}
# Load the current connections.
global_connection_store.get_connection_parameters_from_yaml_file()
# Insert the pre-defined dictionaries to the connection store, so there are at least two dictionaries.
global_connection_store.save_connection_parameters_in_yaml_file(first_connection_dictionary)
global_connection_store.save_connection_parameters_in_yaml_file(second_connection_dictionary)
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a start progress dialog.
start_progress_dialog = StartProgressDialog()
# Start the progress bar.
start_progress_dialog.start_progress_bar()
# Now the step should be start at 0.
assert start_progress_dialog.float_step == 0
# The step size should be smaller than 100, because there are at least two connection parameters in the global
# connection store.
assert start_progress_dialog.step_size < 100
# Clean up, delete the two created connections.
global_connection_store.delete_connection(first_connection_dictionary)
global_connection_store.delete_connection(second_connection_dictionary)

146
tests/test_table_edit.py Normal file
View File

@@ -0,0 +1,146 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.models.treemodel import TableNode
from pygadmin.widgets.table_edit import TableEditDialog
from pygadmin.configurator import global_app_configurator
class TestTableEditDialogMethods(unittest.TestCase):
"""
Test the basic methods and the behavior of the table edit dialog.
"""
def test_dialog_without_node(self):
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Add None instead of a node to the dialog.
table_edit_dialog = TableEditDialog(None)
# The window title of the dialog should be a string with an error.
assert table_edit_dialog.windowTitle() == "Node Input Error"
def test_initial_attributes(self):
"""
Test the existence of some relevant attributes of the dialog.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an existing and valid table node for testing.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Add the table node to the dialog.
table_edit_dialog = TableEditDialog(table_node)
# The selected table node should be the used table node.
assert table_edit_dialog.selected_table_node == table_node
# The database connection of the dialog should be the connection of the table node.
assert table_edit_dialog.database_connection == table_node._database_connection
def test_checkbox_initialization(self):
"""
Test the correct initialization of the checkbox.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an existing and valid table node for testing.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Add the table node to the dialog.
table_edit_dialog = TableEditDialog(table_node)
# Get the current configuration of the checkbox.
checkbox_configuration = global_app_configurator.get_single_configuration(
table_edit_dialog.checkbox_configuration_name)
# If the configuration is True, the checkbox should be checked.
if checkbox_configuration is True:
assert table_edit_dialog.update_immediately_checkbox.isChecked() is True
# If the configuration is False or None, the checkbox should not be checked.
else:
assert table_edit_dialog.update_immediately_checkbox.isChecked() is False
def test_get_select_query(self):
"""
Test the function for getting the select query with an empty condition in the condition line edit and with a
text in the line edit.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an existing and valid table node for testing.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Add the table node to the dialog.
table_edit_dialog = TableEditDialog(table_node)
# The current select query should contain a statement for selecting all values with limit 1000 in the given
# table.
assert table_edit_dialog.get_select_query() == "SELECT * FROM {} LIMIT 1000".format(
table_edit_dialog.selected_table_node.name)
# Define a where condition for further testing.
test_where_condition = "test_column='test_value'"
# Set the where condition in the line edit.l
table_edit_dialog.condition_line_edit.setText(test_where_condition)
# The current select query should contain the where condition in addition to the previous select query.
assert table_edit_dialog.get_select_query() == "SELECT * FROM {} WHERE {} LIMIT 1000".format(
table_edit_dialog.selected_table_node.name, test_where_condition)
def test_update_statement(self):
"""
Test the current state of the update label, which contains the update query.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an existing and valid table node for testing.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Add the table node to the dialog.
table_edit_dialog = TableEditDialog(table_node)
# The update label contains the update statement. Without changing a value in the table, the label contains
# just an UPDATE with the name of the table.
assert table_edit_dialog.update_label.text() == "UPDATE {}".format(table_edit_dialog.selected_table_node.name)
def test_checkbox_change(self):
"""
Test the check changes in the checkbox for updating the table immediately.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create an existing and valid table node for testing.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Add the table node to the dialog.
table_edit_dialog = TableEditDialog(table_node)
# Set the checkbox to checked.
table_edit_dialog.update_immediately_checkbox.setChecked(True)
# The update elements should be invisible now.
assert table_edit_dialog.update_label.isVisible() is False
assert table_edit_dialog.update_button.isVisible() is False
# Set the checkbox to unchecked.
table_edit_dialog.update_immediately_checkbox.setChecked(False)
# The update elements should be visible now.
assert table_edit_dialog.update_label.isVisible() is True
assert table_edit_dialog.update_button.isVisible() is True

View File

@@ -0,0 +1,43 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.table_information import TableInformationDialog
from pygadmin.models.treemodel import TableNode
class TestTableInformationDialogMethods(unittest.TestCase):
"""
Test the functionality and methods of the table information dialog.
"""
def test_dialog_without_node(self):
"""
Test the dialog without a valid node and None instead.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a table information dialog with None as node, which is invalid.
table_information_dialog = TableInformationDialog(None)
# The window title of the widget should show an error.
assert table_information_dialog.windowTitle() == "Node Input Error"
def test_initial_attributes_with_node(self):
"""
Test the initial attributes of the dialog with a valid table node.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Define a valid table node.
table_node = TableNode("test", "localhost", "testuser", "testdb", 5432, 10000)
# Create a table information dialog with the table node.
table_information_dialog = TableInformationDialog(table_node)
# The selected table node of the dialog should be the created table node.
assert table_information_dialog.selected_table_node == table_node
# The parameter for full definition is not filled, so it should use the default value True.
assert table_information_dialog.full_definition is True

138
tests/test_tablemodel.py Normal file
View File

@@ -0,0 +1,138 @@
import unittest
from PyQt5.QtCore import Qt
from pygadmin.models.tablemodel import TableModel
class TestTableModelMethods(unittest.TestCase):
"""
Use a class for testing the different methods of the table model.
"""
def test_initial_data_list(self):
"""
Test the creation of a table model and check the resulting data list.
"""
# Define a data list.
test_data = [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"], ["row D", "row E", "row F"]]
table_model = TableModel(test_data)
# Check the data list of the model.
assert test_data == table_model.data_list
def test_correct_row_count(self):
"""
Test the correct row count for a normal and valid data list.
"""
test_data = [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"], ["row D", "row E", "row F"]]
table_model = TableModel(test_data)
# Describe the row count as the length of the test data list - 1, because the header is not a row.
assert table_model.rowCount() == len(test_data) - 1
def test_correct_column_count(self):
"""
Test the correct column count for a normal and valid data list.
"""
test_data = [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"], ["row D", "row E", "row F"]]
table_model = TableModel(test_data)
# The first list contains all header elements and describes the number of columns.
assert table_model.columnCount() == len(test_data[0])
def test_data_type(self):
"""
Test with different types the correct result of the data in the table model. Almost every value should cause the
return of a string.
"""
# Define different kinds of test data: Numbers in the header, booleans (and None) as first row, numbers as
# second and strings as third.
test_data = [[0, 1, 2], [True, False, None], [4, 5, 6], ["test", "1234", "meow"]]
table_model = TableModel(test_data)
# Get the first item in the first row, check for a string and for the correct value.
first_row_item = table_model.data(table_model.index(0, 0))
assert isinstance(first_row_item, str)
assert first_row_item == "True"
# Get the first item in the second row, check for a string and for the correct value.
second_row_item = table_model.data(table_model.index(1, 0))
assert isinstance(second_row_item, str)
assert second_row_item == "4"
# Get the first item in the third row, check for a string and for the correct value.
third_row_item = table_model.data(table_model.index(2, 0))
assert isinstance(third_row_item, str)
assert third_row_item == "test"
# Get the first item in the fourth row, but this row does not exist, so it should return None. None is not
# casted to a string, so there is just a check for None.
fourth_row_item = table_model.data(table_model.index(3, 0))
assert fourth_row_item is None
def test_horizontal_header_data(self):
"""
Test the correct display of data with a horizontal header.
"""
# Define a first list as extra list, because this list contains the header.
first_list = ["column 0", "column 1", "column 2"]
test_data = [first_list, ["row A", "row B", "row C"], ["row D", "row E", "row F"]]
table_model = TableModel(test_data)
# Check every number in the header.
for header_description_number in range(len(first_list) - 1):
# Get the data in the header by a horizontal orientation.
header_data = table_model.headerData(header_description_number, Qt.Horizontal)
# Check, if the item in the header is the same as the item in the first list, which is the header list.
assert header_data == first_list[header_description_number]
def test_vertical_header_data(self):
"""
Test the correct display of data with a vertical header.
"""
test_data = [["column 0", "column 1", "column 2"], ["row A", "row B", "row C"], ["row D", "row E", "row F"]]
table_model = TableModel(test_data)
# Check for every element in the test data list.
for row_number in range(len(test_data) - 1):
# Get the data at the row number with a vertical orientation.
header_data = table_model.headerData(row_number, Qt.Vertical)
# The data for a vertical header is numeric, so from 1 to whatever and because of this, off by one needs to
# be considered.
assert header_data == row_number + 1
def test_correct_row_count_with_empty_list(self):
"""
Test the correct row count with an empty data list.
"""
test_data = []
table_model = TableModel(test_data)
# For an empty list, the row count should be 0.
assert table_model.rowCount() == 0
def test_correct_column_count_with_empty_list(self):
"""
Test the correct column count with an empty data list.
"""
test_data = []
table_model = TableModel(test_data)
# For an empty data list, the column count should be 0.
assert table_model.columnCount() == 0
def test_false_type_input(self):
"""
Test the behavior of the table model for a data list, which is not a list.
"""
# Define the test data as None.
test_data = None
table_model = TableModel(test_data)
# For a data list, which is not a list, the new and internal data list of the table model should be an empty
# list.
assert table_model.data_list == []

146
tests/test_tree.py Normal file
View File

@@ -0,0 +1,146 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.widgets.tree import TreeWidget
from pygadmin.connectionstore import global_connection_store
from pygadmin.models.treemodel import ServerNode
class TestTreeWidgetMethods(unittest.TestCase):
"""
Test the basic functionality, correct behavior and some functions of the tree widget.
"""
def test_initial_attributes(self):
"""
Test some of the initial attributes of the widget.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create a tree widget.
tree_widget = TreeWidget()
# At the start of the widget, there should not be a selected index.
assert tree_widget.selected_index is False
# Check for the existence and correct instance of the server node list.
assert isinstance(tree_widget.server_nodes, list)
def test_find_new_relevant_parameters(self):
"""
Test the function for finding new relevant connection parameters.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create a tree widget.
tree_widget = TreeWidget()
# Add potential existing nodes to the tree widget.
for connection_dictionary in tree_widget.find_new_relevant_parameters():
new_server_node = ServerNode(connection_dictionary["Host"],
connection_dictionary["Host"],
connection_dictionary["Username"],
connection_dictionary["Port"],
connection_dictionary["Timeout"])
tree_widget.server_nodes.append(new_server_node)
# After the start and without new relevant connection parameters, the function should return an empty list.
assert tree_widget.find_new_relevant_parameters() == []
# Define new connection parameters, so new relevant parameters can be found.
new_connection_parameters = {"Host": "127.0.01",
"Database": "testdb",
"Port": 5432,
"Username": "testuser"}
# Get the current number of the connection parameters in the connection store and use it as new position for new
# connection parameters.
position = global_connection_store.get_number_of_connection_parameters()
# Save the new defined connection parameters in the connection store.
global_connection_store.save_connection_parameters_in_yaml_file(new_connection_parameters)
# Get the new and relevant parameters out of the tree widget.
new_relevant_parameters = tree_widget.find_new_relevant_parameters(position)[0]
# Check for the correct values for the given keys in the dictionary, because they should be identical.
assert new_connection_parameters["Database"] == new_relevant_parameters["Database"]
assert new_connection_parameters["Host"] == new_relevant_parameters["Host"]
assert new_connection_parameters["Port"] == new_relevant_parameters["Port"]
assert new_connection_parameters["Username"] == new_relevant_parameters["Username"]
# Delete the new connection parameters as a clean up.
global_connection_store.delete_connection(new_connection_parameters)
def test_create_new_server_node(self):
"""
Test the method for creating a new server node.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create a tree widget.
tree_widget = TreeWidget()
# Define connection parameters for a new server node.
server_node_connection_parameters = {"Host": "testhost",
"Database": "testdb",
"Port": 5432,
"Username": "testuser",
"Timeout": 10000}
# Create a new server node with the tree widget.
new_server_node = tree_widget.create_new_server_node(server_node_connection_parameters)
# As a result, the created node should be a server node.
assert isinstance(new_server_node, ServerNode)
# Append the node to the list of server nodes, so the next assertion is checked correctly.
tree_widget.server_nodes.append(new_server_node)
# The creation of a new server node should return None, because there is a duplicate.
assert tree_widget.create_new_server_node(server_node_connection_parameters) is None
def test_check_server_node_for_duplicate(self):
"""
Test the method for checking the parameters of a potentially new server node for a duplicate.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create a tree widget.
tree_widget = TreeWidget()
# Define connection parameters for a new server node.
server_node_connection_parameters = {"Host": "testhost",
"Database": "testdb",
"Port": 5432,
"Username": "testuser",
"Timeout": 10000}
# There should not be a server node with the connection parameters of the new server node.
assert tree_widget.check_server_node_for_duplicate(server_node_connection_parameters) is False
# Create a new server node.
new_server_node = tree_widget.create_new_server_node(server_node_connection_parameters)
# Append the new node to the list of server nodes.
tree_widget.server_nodes.append(new_server_node)
# The check for a duplicate with the same and old parameters should return True, because there is a duplicate.
assert tree_widget.check_server_node_for_duplicate(server_node_connection_parameters) is True
def test_append_new_node(self):
"""
Test the method for appending a new node in the tree widget.
"""
# Create an app, because this is necessary for testing a QWidget.
app = QApplication(sys.argv)
# Create a tree widget.
tree_widget = TreeWidget()
# Create a new server node.
server_node = ServerNode("testhost", "testhost", "testuser", 5432)
# Use the method of the tree widget for appending a new server node.
tree_widget.append_new_node(server_node)
# Check for the existence of the new server node in the server node list of the tree widget.
assert server_node in tree_widget.server_nodes

82
tests/test_treemodel.py Normal file
View File

@@ -0,0 +1,82 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication
from pygadmin.models.treemodel import ServerNode, DatabaseNode, SchemaNode, TablesNode, ViewsNode, TableNode, ViewNode
class TestTreeMethods(unittest.TestCase):
"""
Use a class for testing the methods of the tree and the tree model.
"""
def test_create_server_node(self):
"""
Test the creation of a server node.
"""
# A QApplication is necessary for the usage of a QPixmap, which is part of the Server Node.
app = QApplication(sys.argv)
# Create a test node with static connection parameters.
ServerNode(name="localhost",
host="localhost",
user="testuser",
database="testdb",
port=5432,
timeout=5000)
def test_node_children(self):
# A QApplication is necessary for the usage of a QPixmap, which is part of the Server Node.
app = QApplication(sys.argv)
# Create a test node with static connection parameters.
server_node = ServerNode(name="localhost",
host="localhost",
user="testuser",
database="testdb",
port=5432,
timeout=5000)
# The child at row and column 0 of a server node is a database node for a correct and fully functional database
# connection.
database_node = server_node.child(0, 0)
# Check for the right instance.
assert isinstance(database_node, DatabaseNode)
# The child at row and column 0 of a database node is a schema node.
schema_node = database_node.child(0, 0)
# Check for the right instance.
assert isinstance(schema_node, SchemaNode)
# The child at row and column 0 of a schema node is a tables node.
tables_node = schema_node.child(0, 0)
# Check for the right instance.
assert isinstance(tables_node, TablesNode)
# The child at row 1 and column 0 of a schema node is a views node.
views_node = schema_node.child(1, 0)
# Check for the right instance.
assert isinstance(views_node, ViewsNode)
# The child at row and column 0 of a tables node is a table node.
table_node = tables_node.child(0, 0)
# Check for the right instance.
assert isinstance(table_node, TableNode)
# The child at row and column 0 of a views node is a view node.
view_node = views_node.child(0, 0)
# Check for the right instance.
assert isinstance(view_node, ViewNode)
def test_invalid_connection_of_node(self):
# A QApplication is necessary for the usage of a QPixmap, which is part of the Server Node.
app = QApplication(sys.argv)
# Create a test node with static connection parameters. The host contains an invalid parameter, which results in
# an invalid database connection.
server_node = ServerNode(name="localhost",
host="local",
user="testuser",
database="testdb",
port=5432,
timeout=5000)
# The child of a server node should be None for an invalid connection.
assert server_node.child(0, 0) is None

View File

@@ -0,0 +1,27 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication, QLabel
from pygadmin.widgets.version_information_dialog import VersionInformationDialog
class TestVersionInformationDialogMethods(unittest.TestCase):
"""
Test the methods and behavior of the version information dialog.
"""
def test_initial_attributes(self):
"""
Test the initial attributes of the dialog.
"""
# Create an app, because this is necessary for testing a QDialog.
app = QApplication(sys.argv)
# Create a version information dialog.
version_information_dialog = VersionInformationDialog()
# The dialog should not be modal.
assert version_information_dialog.isModal() is False
# The version label should be a QLabel.
assert isinstance(version_information_dialog.version_label, QLabel)

View File

@@ -0,0 +1,41 @@
import sys
import unittest
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget
from pygadmin.widgets.widget_icon_adder import IconAdder
class TestWidgetIconAdderMethods(unittest.TestCase):
"""
Test the functionality of the widget icon adder.
"""
def test_initial_attributes(self):
"""
Test the initial attributes of the icon adder.
"""
# Create an app, because this is necessary for testing a Qt elements.
app = QApplication(sys.argv)
# Create an icon adder.
icon_adder = IconAdder()
# The icon should be a QIcon.
assert isinstance(icon_adder.window_icon, QIcon)
def test_add_icon(self):
"""
Test the method for adding an icon.
"""
# Create an app, because this is necessary for testing a Qt elements.
app = QApplication(sys.argv)
# Create an icon adder.
icon_adder = IconAdder()
# Create a test widget.
test_widget = QWidget()
# Add an icon to the test widget.
icon_adder.add_icon_to_widget(test_widget)
# The name of the window icon of the test widget and of the icon adder should be the same.
assert test_widget.windowIcon().name() == icon_adder.window_icon.name()