From ee71bcae9a424edc69a3bc77a264d024106e31f4 Mon Sep 17 00:00:00 2001 From: Ted Lawson Date: Thu, 17 Aug 2023 03:05:52 -0700 Subject: [PATCH] DRY tests, increase coverage. By @bigtedde (#1769) --- tests/integration/conftest.py | 15 ++++- tests/integration/test_archives.py | 67 ++++--------------- tests/integration/test_borg.py | 9 +-- tests/integration/test_repo.py | 6 +- tests/unit/conftest.py | 15 ++++- tests/unit/test_archives.py | 100 +++++++++++++++-------------- tests/unit/test_diff.py | 9 +-- 7 files changed, 99 insertions(+), 122 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 3d67fc64..683271f5 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -19,7 +19,7 @@ from vorta.store.models import ( WifiSettingModel, ) from vorta.utils import borg_compat -from vorta.views.main_window import MainWindow +from vorta.views.main_window import ArchiveTab, MainWindow models = [ RepoModel, @@ -206,6 +206,19 @@ def rootdir(): return os.path.dirname(os.path.abspath(__file__)) +@pytest.fixture() +def archive_env(qapp, qtbot): + """ + Common setup for integration tests involving the archive tab. + """ + main: MainWindow = qapp.main_window + tab: ArchiveTab = main.archiveTab + main.tabWidget.setCurrentIndex(3) + tab.refresh_archive_list() + qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + return main, tab + + @pytest.fixture(autouse=True) def min_borg_version(borg_version, request): if request.node.get_closest_marker('min_borg_version'): diff --git a/tests/integration/test_archives.py b/tests/integration/test_archives.py index e74f9bb3..a32df06d 100644 --- a/tests/integration/test_archives.py +++ b/tests/integration/test_archives.py @@ -18,11 +18,9 @@ def test_repo_list(qapp, qtbot): """Test that the archives are created and repo list is populated correctly""" main = qapp.main_window tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) tab.refresh_archive_list() qtbot.waitUntil(lambda: not tab.bCheck.isEnabled(), **pytest._wait_defaults) - assert not tab.bCheck.isEnabled() qtbot.waitUntil(lambda: 'Refreshing archives done.' in main.progressText.text(), **pytest._wait_defaults) @@ -31,30 +29,18 @@ def test_repo_list(qapp, qtbot): assert tab.bCheck.isEnabled() -def test_repo_prune(qapp, qtbot): +def test_repo_prune(qapp, qtbot, archive_env): """Test for archive pruning""" - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) - + main, tab = archive_env qtbot.mouseClick(tab.bPrune, QtCore.Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: 'Pruning old archives' in main.progressText.text(), **pytest._wait_defaults) qtbot.waitUntil(lambda: 'Refreshing archives done.' in main.progressText.text(), **pytest._wait_defaults) @pytest.mark.min_borg_version('1.2.0a1') -def test_repo_compact(qapp, qtbot): +def test_repo_compact(qapp, qtbot, archive_env): """Test for archive compaction""" - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) - + main, tab = archive_env qtbot.waitUntil(lambda: tab.compactButton.isEnabled(), **pytest._wait_defaults) assert tab.compactButton.isEnabled() @@ -62,14 +48,9 @@ def test_repo_compact(qapp, qtbot): qtbot.waitUntil(lambda: 'compaction freed about' in main.logText.text().lower(), **pytest._wait_defaults) -def test_check(qapp, qtbot): +def test_check(qapp, qtbot, archive_env): """Test for archive consistency check""" - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + main, tab = archive_env qapp.check_failed_event.disconnect() @@ -81,7 +62,7 @@ def test_check(qapp, qtbot): @pytest.mark.skipif(sys.platform == 'darwin', reason="Macos fuse support is uncertain") -def test_mount(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir): +def test_mount(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir, archive_env): """Test for archive mounting and unmounting""" def psutil_disk_partitions(**kwargs): @@ -91,12 +72,7 @@ def test_mount(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir): monkeypatch.setattr(psutil, "disk_partitions", psutil_disk_partitions) monkeypatch.setattr(vorta.views.archive_tab, "choose_file_dialog", choose_file_dialog) - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + main, tab = archive_env tab.archiveTable.selectRow(0) qtbot.waitUntil(lambda: tab.bMountRepo.isEnabled(), **pytest._wait_defaults) @@ -114,14 +90,9 @@ def test_mount(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir): qtbot.waitUntil(lambda: tab.mountErrors.text().startswith('Un-mounted successfully.'), **pytest._wait_defaults) -def test_archive_extract(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir): +def test_archive_extract(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir, archive_env): """Test for archive extraction""" - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + main, tab = archive_env tab.archiveTable.selectRow(2) tab.extract_action() @@ -139,14 +110,9 @@ def test_archive_extract(qapp, qtbot, monkeypatch, choose_file_dialog, tmpdir): assert [item.basename for item in tmpdir.listdir()] == ['private' if sys.platform == 'darwin' else 'tmp'] -def test_archive_delete(qapp, qtbot, mocker): +def test_archive_delete(qapp, qtbot, mocker, archive_env): """Test for archive deletion""" - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + main, tab = archive_env archivesCount = tab.archiveTable.rowCount() @@ -160,14 +126,9 @@ def test_archive_delete(qapp, qtbot, mocker): assert tab.archiveTable.rowCount() == archivesCount - 1 -def test_archive_rename(qapp, qtbot, mocker): +def test_archive_rename(qapp, qtbot, mocker, archive_env): """Test for archive renaming""" - main = qapp.main_window - tab = main.archiveTab - - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + main, tab = archive_env tab.archiveTable.selectRow(0) new_archive_name = 'idf89d8f9d8fd98' diff --git a/tests/integration/test_borg.py b/tests/integration/test_borg.py index 2a481710..0af84a96 100644 --- a/tests/integration/test_borg.py +++ b/tests/integration/test_borg.py @@ -24,7 +24,6 @@ def test_borg_prune(qapp, qtbot): assert blocker.args[0]['returncode'] == 0 -# test borg info def test_borg_repo_info(qapp, qtbot, tmpdir): """This test runs borg info on a test repo directly without UI""" repo_info = { @@ -45,14 +44,8 @@ def test_borg_repo_info(qapp, qtbot, tmpdir): assert blocker.args[0]['returncode'] == 0 -def test_borg_archive_info(qapp, qtbot, tmpdir): +def test_borg_archive_info(qapp, qtbot, archive_env): """Check that archive info command works""" - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - tab.refresh_archive_list() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() > 0, **pytest._wait_defaults) - params = BorgInfoArchiveJob.prepare(vorta.store.models.BackupProfileModel.select().first(), "test-archive1") thread = BorgInfoArchiveJob(params['cmd'], params, qapp) diff --git a/tests/integration/test_repo.py b/tests/integration/test_repo.py index 5fb4e972..e4751b91 100644 --- a/tests/integration/test_repo.py +++ b/tests/integration/test_repo.py @@ -7,11 +7,9 @@ from PyQt6 import QtCore from vorta.store.models import ArchiveModel, EventLogModel -def test_create(qapp, qtbot): +def test_create(qapp, qtbot, archive_env): """Test for manual archive creation""" - main = qapp.main_window - main.archiveTab.refresh_archive_list() - qtbot.waitUntil(lambda: main.archiveTab.archiveTable.rowCount() > 0, **pytest._wait_defaults) + main, tab = archive_env qtbot.mouseClick(main.createStartBtn, QtCore.Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: 'Backup finished.' in main.progressText.text(), **pytest._wait_defaults) diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index e2ac7d4f..e622a211 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -17,7 +17,7 @@ from vorta.store.models import ( SourceFileModel, WifiSettingModel, ) -from vorta.views.main_window import MainWindow +from vorta.views.main_window import ArchiveTab, MainWindow models = [ RepoModel, @@ -105,3 +105,16 @@ def borg_json_output(): @pytest.fixture def rootdir(): return os.path.dirname(os.path.abspath(__file__)) + + +@pytest.fixture() +def archive_env(qapp, qtbot): + """ + Common setup for unit tests involving the archive tab. + """ + main: MainWindow = qapp.main_window + tab: ArchiveTab = main.archiveTab + main.tabWidget.setCurrentIndex(3) + tab.populate_from_profile() + qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2, **pytest._wait_defaults) + return main, tab diff --git a/tests/unit/test_archives.py b/tests/unit/test_archives.py index a37dcfd8..c17bf624 100644 --- a/tests/unit/test_archives.py +++ b/tests/unit/test_archives.py @@ -30,18 +30,15 @@ def test_prune_intervals(qapp, qtbot): assert getattr(profile, f'prune_{i}') == 9 -def test_repo_list(qapp, qtbot, mocker, borg_json_output): - main = qapp.main_window - tab = main.archiveTab +def test_repo_list(qapp, qtbot, mocker, borg_json_output, archive_env): + main, tab = archive_env stdout, stderr = borg_json_output('list') popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0) mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result) - main.tabWidget.setCurrentIndex(3) tab.refresh_archive_list() qtbot.waitUntil(lambda: not tab.bCheck.isEnabled(), **pytest._wait_defaults) - assert not tab.bCheck.isEnabled() qtbot.waitUntil(lambda: 'Refreshing archives done.' in main.progressText.text(), **pytest._wait_defaults) @@ -50,11 +47,9 @@ def test_repo_list(qapp, qtbot, mocker, borg_json_output): assert tab.bCheck.isEnabled() -def test_repo_prune(qapp, qtbot, mocker, borg_json_output): - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - tab.populate_from_profile() +def test_repo_prune(qapp, qtbot, mocker, borg_json_output, archive_env): + main, tab = archive_env + stdout, stderr = borg_json_output('prune') popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0) mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result) @@ -64,12 +59,10 @@ def test_repo_prune(qapp, qtbot, mocker, borg_json_output): qtbot.waitUntil(lambda: 'Refreshing archives done.' in main.progressText.text(), **pytest._wait_defaults) -def test_repo_compact(qapp, qtbot, mocker, borg_json_output): - main = qapp.main_window - tab = main.archiveTab +def test_repo_compact(qapp, qtbot, mocker, borg_json_output, archive_env): vorta.utils.borg_compat.version = '1.2.0' - main.tabWidget.setCurrentIndex(3) - tab.populate_from_profile() + main, tab = archive_env + stdout, stderr = borg_json_output('compact') popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0) mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result) @@ -82,11 +75,8 @@ def test_repo_compact(qapp, qtbot, mocker, borg_json_output): vorta.utils.borg_compat.version = '1.1.0' -def test_check(qapp, mocker, borg_json_output, qtbot): - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - tab.populate_from_profile() +def test_check(qapp, mocker, borg_json_output, qtbot, archive_env): + main, tab = archive_env stdout, stderr = borg_json_output('check') popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0) @@ -97,17 +87,13 @@ def test_check(qapp, mocker, borg_json_output, qtbot): qtbot.waitUntil(lambda: success_text in main.logText.text(), **pytest._wait_defaults) -def test_mount(qapp, qtbot, mocker, borg_json_output, monkeypatch, choose_file_dialog): +def test_mount(qapp, qtbot, mocker, borg_json_output, monkeypatch, choose_file_dialog, archive_env): def psutil_disk_partitions(**kwargs): DiskPartitions = namedtuple('DiskPartitions', ['device', 'mountpoint']) return [DiskPartitions('borgfs', '/tmp')] monkeypatch.setattr(psutil, "disk_partitions", psutil_disk_partitions) - - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - tab.populate_from_profile() + main, tab = archive_env tab.archiveTable.selectRow(0) stdout, stderr = borg_json_output('prune') # TODO: fully mock mount command? @@ -129,14 +115,8 @@ def test_mount(qapp, qtbot, mocker, borg_json_output, monkeypatch, choose_file_d qtbot.waitUntil(lambda: tab.mountErrors.text().startswith('Un-mounted successfully.'), **pytest._wait_defaults) -def test_archive_extract(qapp, qtbot, mocker, borg_json_output): - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - - tab.populate_from_profile() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2) - +def test_archive_extract(qapp, qtbot, mocker, borg_json_output, archive_env): + main, tab = archive_env tab.archiveTable.selectRow(0) stdout, stderr = borg_json_output('list_archive') popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0) @@ -144,20 +124,14 @@ def test_archive_extract(qapp, qtbot, mocker, borg_json_output): tab.extract_action() qtbot.waitUntil(lambda: hasattr(tab, '_window'), **pytest._wait_defaults) - # qtbot.waitUntil(lambda: tab._window == qapp.activeWindow(), **pytest._wait_defaults) model = tab._window.model assert model.root.children[0].subpath == 'home' assert 'test-archive, 2000' in tab._window.archiveNameLabel.text() -def test_archive_delete(qapp, qtbot, mocker, borg_json_output): - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - - tab.populate_from_profile() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2) +def test_archive_delete(qapp, qtbot, mocker, borg_json_output, archive_env): + main, tab = archive_env tab.archiveTable.selectRow(0) stdout, stderr = borg_json_output('delete') @@ -170,13 +144,43 @@ def test_archive_delete(qapp, qtbot, mocker, borg_json_output): assert tab.archiveTable.rowCount() == 1 -def test_archive_rename(qapp, qtbot, mocker, borg_json_output): - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) +def test_archive_copy(qapp, qtbot, monkeypatch, mocker, archive_env): + main, tab = archive_env - tab.populate_from_profile() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2) + # mock the clipboard to ensure no changes are made to it during testing + mocker.patch.object(qapp.clipboard(), "setMimeData") + clipboard_spy = mocker.spy(qapp.clipboard(), "setMimeData") + + # test 'archive_copy()' by passing it an index to copy + index = tab.archiveTable.model().index(0, 0) + tab.archive_copy(index) + assert clipboard_spy.call_count == 1 + actual_data = clipboard_spy.call_args[0][0] # retrieves the QMimeData() object used in method call + assert actual_data.text() == "test-archive" + + # test 'archive_copy()' by selecting a row to copy + tab.archiveTable.selectRow(1) + tab.archive_copy() + assert clipboard_spy.call_count == 2 + actual_data = clipboard_spy.call_args[0][0] # retrieves the QMimeData() object used in method call + assert actual_data.text() == "test-archive1" + + +def test_refresh_archive_info(qapp, qtbot, mocker, borg_json_output, archive_env): + main, tab = archive_env + tab.archiveTable.selectRow(0) + stdout, stderr = borg_json_output('info') + popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0) + mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result) + + with qtbot.waitSignal(tab.bRefreshArchive.clicked, timeout=5000): + qtbot.mouseClick(tab.bRefreshArchive, QtCore.Qt.MouseButton.LeftButton) + + qtbot.waitUntil(lambda: tab.mountErrors.text() == 'Refreshed archives.', **pytest._wait_defaults) + + +def test_archive_rename(qapp, qtbot, mocker, borg_json_output, archive_env): + main, tab = archive_env tab.archiveTable.selectRow(0) new_archive_name = 'idf89d8f9d8fd98' diff --git a/tests/unit/test_diff.py b/tests/unit/test_diff.py index 7db44b2e..191c575a 100644 --- a/tests/unit/test_diff.py +++ b/tests/unit/test_diff.py @@ -18,13 +18,8 @@ from vorta.views.diff_result import ( @pytest.mark.parametrize( 'json_mock_file,folder_root', [('diff_archives', 'test'), ('diff_archives_dict_issue', 'Users')] ) -def test_archive_diff(qapp, qtbot, mocker, borg_json_output, json_mock_file, folder_root): - main = qapp.main_window - tab = main.archiveTab - main.tabWidget.setCurrentIndex(3) - - tab.populate_from_profile() - qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2) +def test_archive_diff(qapp, qtbot, mocker, borg_json_output, json_mock_file, folder_root, archive_env): + main, tab = archive_env stdout, stderr = borg_json_output(json_mock_file) popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)