diff --git a/tests_gui_local/commontests.py b/tests_gui_local/GuiBaseTest.py
similarity index 72%
rename from tests_gui_local/commontests.py
rename to tests_gui_local/GuiBaseTest.py
index 27e406c1..e7d25031 100644
--- a/tests_gui_local/commontests.py
+++ b/tests_gui_local/GuiBaseTest.py
@@ -18,7 +18,7 @@ from onionshare_gui.mode.share_mode import ShareMode
 from onionshare_gui.mode.receive_mode import ReceiveMode
 
 
-class CommonTests(object):
+class GuiBaseTest(object):
     @staticmethod
     def set_up(test_settings):
         '''Create GUI with given settings'''
@@ -59,6 +59,7 @@ class CommonTests(object):
         except:
             pass
 
+
     def test_gui_loaded(self):
         '''Test that the GUI actually is shown'''
         self.assertTrue(self.gui.show)
@@ -168,7 +169,6 @@ class CommonTests(object):
         else:
             self.assertIsNone(mode.server_status.web.slug, r'(\w+)-(\w+)')
 
-
     def test_url_description_shown(self, mode):
         '''Test that the URL label is showing'''
         self.assertTrue(mode.server_status.url_description.isVisible())
@@ -337,3 +337,92 @@ class CommonTests(object):
     def test_add_button_visible(self):
         '''Test that the add button should be visible'''
         self.assertTrue(self.gui.share_mode.server_status.file_selection.add_button.isVisible())
+
+
+    # The following are 'groupings' of tests used by other objects that inherit GuiBaseTest
+
+    def run_all_common_setup_tests(self):
+        GuiBaseTest.test_gui_loaded(self)
+        GuiBaseTest.test_windowTitle_seen(self)
+        GuiBaseTest.test_settings_button_is_visible(self)
+        GuiBaseTest.test_server_status_bar_is_visible(self)
+
+    def run_all_share_mode_setup_tests(self):
+        """Tests in share mode prior to starting a share"""
+        GuiBaseTest.test_click_mode(self, self.gui.share_mode)
+        GuiBaseTest.test_file_selection_widget_has_a_file(self)
+        GuiBaseTest.test_history_is_not_visible(self, self.gui.share_mode)
+        GuiBaseTest.test_click_toggle_history(self, self.gui.share_mode)
+        GuiBaseTest.test_history_is_visible(self, self.gui.share_mode)
+        GuiBaseTest.test_deleting_only_file_hides_delete_button(self)
+        GuiBaseTest.test_add_a_file_and_delete_using_its_delete_widget(self)
+        GuiBaseTest.test_file_selection_widget_readd_files(self)
+
+    def run_all_share_mode_started_tests(self, public_mode):
+        """Tests in share mode after starting a share"""
+        GuiBaseTest.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
+        GuiBaseTest.test_server_status_indicator_says_starting(self, self.gui.share_mode)
+        GuiBaseTest.test_add_delete_buttons_hidden(self)
+        GuiBaseTest.test_settings_button_is_hidden(self)
+        GuiBaseTest.test_a_server_is_started(self, self.gui.share_mode)
+        GuiBaseTest.test_a_web_server_is_running(self)
+        GuiBaseTest.test_have_a_slug(self, self.gui.share_mode, public_mode)
+        GuiBaseTest.test_url_description_shown(self, self.gui.share_mode)
+        GuiBaseTest.test_have_copy_url_button(self, self.gui.share_mode)
+        GuiBaseTest.test_server_status_indicator_says_started(self, self.gui.share_mode)
+        GuiBaseTest.test_web_page(self, self.gui.share_mode, 'Total size', public_mode)
+
+    def run_all_share_mode_download_tests(self, public_mode, stay_open):
+        """Tests in share mode after downloading a share"""
+        GuiBaseTest.test_download_share(self, public_mode)
+        GuiBaseTest.test_history_widgets_present(self, self.gui.share_mode)
+        GuiBaseTest.test_server_is_stopped(self, self.gui.share_mode, stay_open)
+        GuiBaseTest.test_web_service_is_stopped(self)
+        GuiBaseTest.test_server_status_indicator_says_closed(self, self.gui.share_mode, stay_open)
+        GuiBaseTest.test_add_button_visible(self)
+        GuiBaseTest.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
+        GuiBaseTest.test_a_server_is_started(self, self.gui.share_mode)
+        GuiBaseTest.test_history_indicator(self, self.gui.share_mode, public_mode)
+
+    def run_all_share_mode_tests(self, public_mode, stay_open):
+        """End-to-end share tests"""
+        GuiBaseTest.run_all_share_mode_setup_tests(self)
+        GuiBaseTest.run_all_share_mode_started_tests(self, public_mode)
+        GuiBaseTest.run_all_share_mode_download_tests(self, public_mode, stay_open)
+
+    def run_all_share_mode_timer_tests(self, public_mode):
+        """Auto-stop timer tests in share mode"""
+        GuiBaseTest.run_all_share_mode_setup_tests(self)
+        GuiBaseTest.test_set_timeout(self, self.gui.share_mode, 5)
+        GuiBaseTest.run_all_share_mode_started_tests(self, public_mode)
+        GuiBaseTest.test_timeout_widget_hidden(self, self.gui.share_mode)
+        GuiBaseTest.test_server_timed_out(self, self.gui.share_mode, 10000)
+        GuiBaseTest.test_web_service_is_stopped(self)
+
+    def run_all_receive_mode_tests(self, public_mode, receive_allow_receiver_shutdown):
+        GuiBaseTest.test_click_mode(self, self.gui.receive_mode)
+        GuiBaseTest.test_history_is_not_visible(self, self.gui.receive_mode)
+        GuiBaseTest.test_click_toggle_history(self, self.gui.receive_mode)
+        GuiBaseTest.test_history_is_visible(self, self.gui.receive_mode)
+        GuiBaseTest.test_server_working_on_start_button_pressed(self, self.gui.receive_mode)
+        GuiBaseTest.test_server_status_indicator_says_starting(self, self.gui.receive_mode)
+        GuiBaseTest.test_settings_button_is_hidden(self)
+        GuiBaseTest.test_a_server_is_started(self, self.gui.receive_mode)
+        GuiBaseTest.test_a_web_server_is_running(self)
+        GuiBaseTest.test_have_a_slug(self, self.gui.receive_mode, public_mode)
+        GuiBaseTest.test_url_description_shown(self, self.gui.receive_mode)
+        GuiBaseTest.test_have_copy_url_button(self, self.gui.receive_mode)
+        GuiBaseTest.test_server_status_indicator_says_started(self, self.gui.receive_mode)
+        GuiBaseTest.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', public_mode)
+        GuiBaseTest.test_upload_file(self, public_mode, '/tmp/OnionShare/test.txt')
+        GuiBaseTest.test_history_widgets_present(self, self.gui.receive_mode)
+        GuiBaseTest.test_counter_incremented(self, self.gui.receive_mode, 1)
+        GuiBaseTest.test_upload_file(self, public_mode, '/tmp/OnionShare/test-2.txt')
+        GuiBaseTest.test_counter_incremented(self, self.gui.receive_mode, 2)
+        GuiBaseTest.test_history_indicator(self, self.gui.receive_mode, public_mode)
+        GuiBaseTest.test_server_is_stopped(self, self.gui.receive_mode, False)
+        GuiBaseTest.test_web_service_is_stopped(self)
+        GuiBaseTest.test_server_status_indicator_says_closed(self, self.gui.receive_mode, False)
+        GuiBaseTest.test_server_working_on_start_button_pressed(self, self.gui.receive_mode)
+        GuiBaseTest.test_a_server_is_started(self, self.gui.receive_mode)
+        GuiBaseTest.test_history_indicator(self, self.gui.receive_mode, public_mode)
diff --git a/tests_gui_local/__init__.py b/tests_gui_local/__init__.py
index bb2b2182..7cf168eb 100644
--- a/tests_gui_local/__init__.py
+++ b/tests_gui_local/__init__.py
@@ -1 +1 @@
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest 
diff --git a/tests_gui_local/onionshare_receive_mode_upload_test.py b/tests_gui_local/onionshare_receive_mode_upload_test.py
index 91013d92..262c7aba 100644
--- a/tests_gui_local/onionshare_receive_mode_upload_test.py
+++ b/tests_gui_local/onionshare_receive_mode_upload_test.py
@@ -12,128 +12,27 @@ from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest
 
-class OnionShareGuiTest(unittest.TestCase):
+class ReceiveModeTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
-            "public_mode": False,
             "receive_allow_receiver_shutdown": True
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=6)
-    def test_click_mode(self):
-        CommonTests.test_click_mode(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=6)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=7)
-    def test_click_toggle_history(self):
-        CommonTests.test_click_toggle_history(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=8)
-    def test_history_is_visible(self):
-        CommonTests.test_history_is_visible(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=8)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=9)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=10)
-    def test_settings_button_is_hidden(self):
-        CommonTests.test_settings_button_is_hidden(self)
-
-    @pytest.mark.run(order=11)
-    def test_a_server_is_started(self):
-       CommonTests.test_a_server_is_started(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=12)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=14)
-    def test_have_a_slug(self):
-       CommonTests.test_have_a_slug(self, self.gui.receive_mode, False)
-
-    @pytest.mark.run(order=15)
-    def test_url_description_shown(self):
-       CommonTests.test_url_description_shown(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=16)
-    def test_have_copy_url_button(self):
-       CommonTests.test_have_copy_url_button(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=17)
-    def test_server_status_indicator_says_started(self):
-        CommonTests.test_server_status_indicator_says_started(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=18)
-    def test_web_page(self):
-        CommonTests.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', False)
-
-    @pytest.mark.run(order=19)
-    def test_upload_file(self):
-        CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test.txt')
-
-    @pytest.mark.run(order=20)
-    def test_history_widgets_present(self):
-        CommonTests.test_history_widgets_present(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=21)
-    def test_counter_incremented(self):
-        CommonTests.test_counter_incremented(self, self.gui.receive_mode, 1)
-
-    @pytest.mark.run(order=22)
-    def test_upload_same_file_is_renamed(self):
-        CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test-2.txt')
-
-    @pytest.mark.run(order=23)
-    def test_upload_count_incremented_again(self):
-        CommonTests.test_counter_incremented(self, self.gui.receive_mode, 2)
-
-    @pytest.mark.run(order=24)
-    def test_history_indicator(self):
-        CommonTests.test_history_indicator(self, self.gui.receive_mode, False)
-
-    @pytest.mark.run(order=25)
-    def test_server_is_stopped(self):
-        CommonTests.test_server_is_stopped(self, self.gui.receive_mode, False)
-
-    @pytest.mark.run(order=26)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=27)
-    def test_server_status_indicator_says_closed(self):
-        CommonTests.test_server_status_indicator_says_closed(self, self.gui.receive_mode, False)
+    def test_run_all_share_mode_tests(self):
+        GuiBaseTest.run_all_receive_mode_tests(self, False, True)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py
index 42f237c9..201402c2 100644
--- a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py
+++ b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py
@@ -8,133 +8,32 @@ import json
 from PyQt5 import QtWidgets
 
 from onionshare.common import Common
-from onionshare.settings import Settings
 from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest
 
-class OnionShareGuiTest(unittest.TestCase):
+class ReceiveModePublicModeTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
             "public_mode": True,
             "receive_allow_receiver_shutdown": True
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=5)
-    def test_click_mode(self):
-        CommonTests.test_click_mode(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=6)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=7)
-    def test_click_toggle_history(self):
-        CommonTests.test_click_toggle_history(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=8)
-    def test_history_is_visible(self):
-        CommonTests.test_history_is_visible(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=9)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=10)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=11)
-    def test_settings_button_is_hidden(self):
-        CommonTests.test_settings_button_is_hidden(self)
-
-    @pytest.mark.run(order=12)
-    def test_a_server_is_started(self):
-       CommonTests.test_a_server_is_started(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=13)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=14)
-    def test_have_a_slug(self):
-       CommonTests.test_have_a_slug(self, self.gui.receive_mode, True)
-
-    @pytest.mark.run(order=15)
-    def test_url_description_shown(self):
-       CommonTests.test_url_description_shown(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=16)
-    def test_have_copy_url_button(self):
-       CommonTests.test_have_copy_url_button(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=17)
-    def test_server_status_indicator_says_started(self):
-        CommonTests.test_server_status_indicator_says_started(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=18)
-    def test_web_page(self):
-        CommonTests.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', True)
-
-    @pytest.mark.run(order=19)
-    def test_upload_file(self):
-        CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test.txt')
-
-    @pytest.mark.run(order=20)
-    def test_history_widgets_present(self):
-        CommonTests.test_history_widgets_present(self, self.gui.receive_mode)
-
-    @pytest.mark.run(order=21)
-    def test_counter_incremented(self):
-        CommonTests.test_counter_incremented(self, self.gui.receive_mode, 1)
-
-    @pytest.mark.run(order=22)
-    def test_upload_same_file_is_renamed(self):
-        CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test-2.txt')
-
-    @pytest.mark.run(order=23)
-    def test_upload_count_incremented_again(self):
-        CommonTests.test_counter_incremented(self, self.gui.receive_mode, 2)
-
-    @pytest.mark.run(order=24)
-    def test_history_indicator(self):
-        CommonTests.test_history_indicator(self, self.gui.receive_mode, True)
-
-    @pytest.mark.run(order=25)
-    def test_server_is_stopped(self):
-        CommonTests.test_server_is_stopped(self, self.gui.receive_mode, False)
-
-    @pytest.mark.run(order=26)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=27)
-    def test_server_status_indicator_says_closed(self):
-        CommonTests.test_server_status_indicator_says_closed(self, self.gui.receive_mode, False)
+    def test_run_all_share_mode_tests(self):
+        GuiBaseTest.run_all_receive_mode_tests(self, True, True)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests_gui_local/onionshare_share_mode_download_test.py b/tests_gui_local/onionshare_share_mode_download_test.py
index 9caad8b1..b24a3a78 100644
--- a/tests_gui_local/onionshare_share_mode_download_test.py
+++ b/tests_gui_local/onionshare_share_mode_download_test.py
@@ -12,139 +12,26 @@ from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest 
 
-class OnionShareGuiTest(unittest.TestCase):
+class ShareModeTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
-            "public_mode": False,
-            "close_after_first_download": True
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=5)
-    def test_file_selection_widget_has_a_file(self):
-        CommonTests.test_file_selection_widget_has_a_file(self)
-
-    @pytest.mark.run(order=7)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=8)
-    def test_click_toggle_history(self):
-        CommonTests.test_click_toggle_history(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=9)
-    def test_history_is_visible(self):
-        CommonTests.test_history_is_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=10)
-    def test_deleting_only_file_hides_delete_button(self):
-        CommonTests.test_deleting_only_file_hides_delete_button(self)
-
-    @pytest.mark.run(order=11)
-    def test_add_a_file_and_delete_using_its_delete_widget(self):
-        CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self)
-
-    @pytest.mark.run(order=12)
-    def test_file_selection_widget_readd_files(self):
-        CommonTests.test_file_selection_widget_readd_files(self)
-
-    @pytest.mark.run(order=13)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=14)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=15)
-    def test_add_delete_buttons_hidden(self):
-        CommonTests.test_add_delete_buttons_hidden(self)
-
-    @pytest.mark.run(order=16)
-    def test_settings_button_is_hidden(self):
-        CommonTests.test_settings_button_is_hidden(self)
-
-    @pytest.mark.run(order=17)
-    def test_a_server_is_started(self):
-       CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=18)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=19)
-    def test_have_a_slug(self):
-        CommonTests.test_have_a_slug(self, self.gui.share_mode, False)
-
-    @pytest.mark.run(order=20)
-    def test_url_description_shown(self):
-        CommonTests.test_url_description_shown(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=21)
-    def test_have_copy_url_button(self):
-        CommonTests.test_have_copy_url_button(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=22)
-    def test_server_status_indicator_says_started(self):
-        CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=23)
-    def test_web_page(self):
-        CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', False)
-
-    @pytest.mark.run(order=24)
-    def test_download_share(self):
-        CommonTests.test_download_share(self, False)
-
-    @pytest.mark.run(order=25)
-    def test_history_widgets_present(self):
-        CommonTests.test_history_widgets_present(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=26)
-    def test_server_is_stopped(self):
-        CommonTests.test_server_is_stopped(self, self.gui.share_mode, False)
-
-    @pytest.mark.run(order=27)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=28)
-    def test_server_status_indicator_says_closed(self):
-        CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, False)
-
-    @pytest.mark.run(order=29)
-    def test_add_button_visible(self):
-        CommonTests.test_add_button_visible(self)
-
-    @pytest.mark.run(order=30)
-    def test_history_indicator(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-        CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-        CommonTests.test_history_indicator(self, self.gui.share_mode, False)
-
+    def test_run_all_share_mode_tests(self):
+        GuiBaseTest.run_all_share_mode_tests(self, False, False)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py
index c7b05543..e59b53f4 100644
--- a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py
+++ b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py
@@ -12,138 +12,27 @@ from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest
 
-class OnionShareGuiTest(unittest.TestCase):
+class ShareModePublicModeTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
-            "public_mode": True
+            "public_mode": True,
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=5)
-    def test_file_selection_widget_has_a_file(self):
-        CommonTests.test_file_selection_widget_has_a_file(self)
-
-    @pytest.mark.run(order=7)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=8)
-    def test_click_toggle_history(self):
-        CommonTests.test_click_toggle_history(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=9)
-    def test_history_is_visible(self):
-        CommonTests.test_history_is_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=10)
-    def test_deleting_only_file_hides_delete_button(self):
-        CommonTests.test_deleting_only_file_hides_delete_button(self)
-
-    @pytest.mark.run(order=11)
-    def test_add_a_file_and_delete_using_its_delete_widget(self):
-        CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self)
-
-    @pytest.mark.run(order=12)
-    def test_file_selection_widget_readd_files(self):
-        CommonTests.test_file_selection_widget_readd_files(self)
-
-    @pytest.mark.run(order=13)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=14)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=15)
-    def test_add_delete_buttons_hidden(self):
-        CommonTests.test_add_delete_buttons_hidden(self)
-
-    @pytest.mark.run(order=16)
-    def test_settings_button_is_hidden(self):
-        CommonTests.test_settings_button_is_hidden(self)
-
-    @pytest.mark.run(order=17)
-    def test_a_server_is_started(self):
-       CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=18)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=19)
-    def test_have_a_slug(self):
-        CommonTests.test_have_a_slug(self, self.gui.share_mode, True)
-
-    @pytest.mark.run(order=20)
-    def test_url_description_shown(self):
-        CommonTests.test_url_description_shown(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=21)
-    def test_have_copy_url_button(self):
-        CommonTests.test_have_copy_url_button(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=22)
-    def test_server_status_indicator_says_started(self):
-        CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=23)
-    def test_web_page(self):
-        CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', True)
-
-    @pytest.mark.run(order=24)
-    def test_download_share(self):
-        CommonTests.test_download_share(self, True)
-
-    @pytest.mark.run(order=25)
-    def test_history_widgets_present(self):
-        CommonTests.test_history_widgets_present(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=26)
-    def test_server_is_stopped(self):
-        CommonTests.test_server_is_stopped(self, self.gui.share_mode, False)
-
-    @pytest.mark.run(order=27)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=28)
-    def test_server_status_indicator_says_closed(self):
-        CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, False)
-
-    @pytest.mark.run(order=29)
-    def test_add_button_visible(self):
-        CommonTests.test_add_button_visible(self)
-
-    @pytest.mark.run(order=30)
-    def test_history_indicator(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-        CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-        CommonTests.test_history_indicator(self, self.gui.share_mode, True)
-
+    def test_run_all_share_mode_tests(self):
+        GuiBaseTest.run_all_share_mode_tests(self, True, False)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py
index 478177c0..9394c34a 100644
--- a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py
+++ b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py
@@ -12,151 +12,27 @@ from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest
 
-class OnionShareGuiTest(unittest.TestCase):
+class ShareModeStayOpenTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
-            "public_mode": True,
-            "close_after_first_download": False
+            "close_after_first_download": False,
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=5)
-    def test_file_selection_widget_has_a_file(self):
-        CommonTests.test_file_selection_widget_has_a_file(self)
-
-    @pytest.mark.run(order=7)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=8)
-    def test_click_toggle_history(self):
-        CommonTests.test_click_toggle_history(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=9)
-    def test_history_is_visible(self):
-        CommonTests.test_history_is_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=10)
-    def test_deleting_only_file_hides_delete_button(self):
-        CommonTests.test_deleting_only_file_hides_delete_button(self)
-
-    @pytest.mark.run(order=11)
-    def test_add_a_file_and_delete_using_its_delete_widget(self):
-        CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self)
-
-    @pytest.mark.run(order=12)
-    def test_file_selection_widget_readd_files(self):
-        CommonTests.test_file_selection_widget_readd_files(self)
-
-    @pytest.mark.run(order=13)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=14)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=15)
-    def test_add_delete_buttons_hidden(self):
-        CommonTests.test_add_delete_buttons_hidden(self)
-
-    @pytest.mark.run(order=16)
-    def test_settings_button_is_hidden(self):
-        CommonTests.test_settings_button_is_hidden(self)
-
-    @pytest.mark.run(order=17)
-    def test_a_server_is_started(self):
-       CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=18)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=19)
-    def test_have_a_slug(self):
-        CommonTests.test_have_a_slug(self, self.gui.share_mode, True)
-
-    @pytest.mark.run(order=20)
-    def test_url_description_shown(self):
-        CommonTests.test_url_description_shown(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=21)
-    def test_have_copy_url_button(self):
-        CommonTests.test_have_copy_url_button(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=22)
-    def test_server_status_indicator_says_started(self):
-        CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=23)
-    def test_web_page(self):
-        CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', True)
-
-    @pytest.mark.run(order=24)
-    def test_download_share(self):
-        CommonTests.test_download_share(self, True)
-
-    @pytest.mark.run(order=25)
-    def test_history_widgets_present(self):
-        CommonTests.test_history_widgets_present(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=26)
-    def test_counter_incremented(self):
-        CommonTests.test_counter_incremented(self, self.gui.share_mode, 1)
-
-    @pytest.mark.run(order=27)
-    def test_download_share_again(self):
-        CommonTests.test_download_share(self, True)
-
-    @pytest.mark.run(order=28)
-    def test_counter_incremented_again(self):
-        CommonTests.test_counter_incremented(self, self.gui.share_mode, 2)
-
-    @pytest.mark.run(order=29)
-    def test_server_is_stopped(self):
-        CommonTests.test_server_is_stopped(self, self.gui.share_mode, True)
-
-    @pytest.mark.run(order=30)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=31)
-    def test_server_status_indicator_says_closed(self):
-        CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, True)
-
-    @pytest.mark.run(order=32)
-    def test_add_button_visible(self):
-        CommonTests.test_add_button_visible(self)
-
-    @pytest.mark.run(order=33)
-    def test_history_indicator(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-        CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-        CommonTests.test_history_indicator(self, self.gui.share_mode, True)
-
+    def test_run_all_share_mode_tests(self):
+        GuiBaseTest.run_all_share_mode_tests(self, False, True)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests_gui_local/onionshare_slug_persistent_test.py b/tests_gui_local/onionshare_slug_persistent_test.py
index f4139afb..ab845f8e 100644
--- a/tests_gui_local/onionshare_slug_persistent_test.py
+++ b/tests_gui_local/onionshare_slug_persistent_test.py
@@ -12,114 +12,37 @@ from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest
 
-class OnionShareGuiTest(unittest.TestCase):
+class ShareModePersistentSlugTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
             "public_mode": False,
             "slug": "",
-            "save_private_key": True
+            "save_private_key": True,
+            "close_after_first_download": False,
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=7)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=8)
-    def test_click_toggle_history(self):
-        CommonTests.test_click_toggle_history(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=9)
-    def test_history_is_visible(self):
-        CommonTests.test_history_is_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=10)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=11)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=12)
-    def test_settings_button_is_hidden(self):
-        CommonTests.test_settings_button_is_hidden(self)
-
-    @pytest.mark.run(order=13)
-    def test_a_server_is_started(self):
-        CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=14)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=15)
-    def test_have_a_slug(self):
-        CommonTests.test_have_a_slug(self, self.gui.share_mode, False)
+    def test_run_all_share_mode_tests(self):
+        GuiBaseTest.run_all_share_mode_tests(self, False, True)
         global slug
         slug = self.gui.share_mode.server_status.web.slug
 
-    @pytest.mark.run(order=16)
-    def test_server_status_indicator_says_started(self):
-        CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=17)
-    def test_server_is_stopped(self):
-        CommonTests.test_server_is_stopped(self, self.gui.share_mode, True)
-
-    @pytest.mark.run(order=18)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=19)
-    def test_server_status_indicator_says_closed(self):
-        CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, True)
-
-    @pytest.mark.run(order=20)
-    def test_server_started_again(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode)
-        CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=21)
+    @pytest.mark.run(order=3)
     def test_have_same_slug(self):
         '''Test that we have the same slug'''
         self.assertEqual(self.gui.share_mode.server_status.web.slug, slug)
 
-    @pytest.mark.run(order=22)
-    def test_server_is_stopped_again(self):
-        CommonTests.test_server_is_stopped(self, self.gui.share_mode, True)
-        CommonTests.test_web_service_is_stopped(self)
-
-    @pytest.mark.run(order=23)
-    def test_history_indicator(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-        CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-        CommonTests.test_history_indicator(self, self.gui.share_mode, False)
-
-
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests_gui_local/onionshare_timer_test.py b/tests_gui_local/onionshare_timer_test.py
index ef55886e..60c616cc 100644
--- a/tests_gui_local/onionshare_timer_test.py
+++ b/tests_gui_local/onionshare_timer_test.py
@@ -12,76 +12,28 @@ from onionshare.web import Web
 from onionshare import onion, strings
 from onionshare_gui import *
 
-from .commontests import CommonTests
+from .GuiBaseTest import GuiBaseTest
 
-class OnionShareGuiTest(unittest.TestCase):
+class ShareModeTimerTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         test_settings = {
             "public_mode": False,
-            "shutdown_timeout": True
+            "shutdown_timeout": True,
         }
-        cls.gui = CommonTests.set_up(test_settings)
+        cls.gui = GuiBaseTest.set_up(test_settings)
 
     @classmethod
     def tearDownClass(cls):
-        CommonTests.tear_down()
+        GuiBaseTest.tear_down()
 
     @pytest.mark.run(order=1)
-    def test_gui_loaded(self):
-        CommonTests.test_gui_loaded(self)
+    def test_run_all_common_setup_tests(self):
+        GuiBaseTest.run_all_common_setup_tests(self)
 
     @pytest.mark.run(order=2)
-    def test_windowTitle_seen(self):
-        CommonTests.test_windowTitle_seen(self)
-
-    @pytest.mark.run(order=3)
-    def test_settings_button_is_visible(self):
-        CommonTests.test_settings_button_is_visible(self)
-
-    @pytest.mark.run(order=4)
-    def test_server_status_bar_is_visible(self):
-        CommonTests.test_server_status_bar_is_visible(self)
-
-    @pytest.mark.run(order=5)
-    def test_file_selection_widget_has_a_file(self):
-        CommonTests.test_file_selection_widget_has_a_file(self)
-
-    @pytest.mark.run(order=7)
-    def test_history_is_not_visible(self):
-        CommonTests.test_history_is_not_visible(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=8)
-    def test_set_timeout(self):
-        CommonTests.test_set_timeout(self, self.gui.share_mode, 5)
-
-    @pytest.mark.run(order=9)
-    def test_server_working_on_start_button_pressed(self):
-        CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=10)
-    def test_server_status_indicator_says_starting(self):
-        CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=11)
-    def test_a_server_is_started(self):
-       CommonTests.test_a_server_is_started(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=12)
-    def test_a_web_server_is_running(self):
-        CommonTests.test_a_web_server_is_running(self)
-
-    @pytest.mark.run(order=13)
-    def test_timeout_widget_hidden(self):
-        CommonTests.test_timeout_widget_hidden(self, self.gui.share_mode)
-
-    @pytest.mark.run(order=14)
-    def test_timeout(self):
-        CommonTests.test_server_timed_out(self, self.gui.share_mode, 10000)
-
-    @pytest.mark.run(order=15)
-    def test_web_service_is_stopped(self):
-        CommonTests.test_web_service_is_stopped(self)
+    def test_run_all_share_mode_timer_tests(self):
+        GuiBaseTest.run_all_share_mode_timer_tests(self, False)
 
 if __name__ == "__main__":
     unittest.main()