diff --git a/qt/python/mantidqt/utils/qt/testing/__init__.py b/qt/python/mantidqt/utils/qt/testing/__init__.py
index 7aee12dd5186f33a0a0b11f28f2051f84a7ee57a..19a8885cfe81a5134675f81103b61d5810b03e8e 100644
--- a/qt/python/mantidqt/utils/qt/testing/__init__.py
+++ b/qt/python/mantidqt/utils/qt/testing/__init__.py
@@ -29,15 +29,17 @@ from mantidqt.utils.qt.plugins import setup_library_paths
 from .modal_tester import ModalTester
 
 
-# Reference to created QApplication instance so that item is kept alive
-QAPP = None
-
-
 def requires_qapp(cls):
     """
     Converts a unittest.TestCase class to a GUI test case by wrapping all
     test methods in a decorator that makes sure that a QApplication is created.
     Qt widgets don't work without QApplication.
+
+    Note: It seems possible to segfault the Python process if the QApplication object
+    is destroyed too late. This seems nearly guaranteed if the QApplication object is stored
+    as a global variable at module scope. For this reason this decorator stores
+    its instance as an object attribute.
+
     Usage:
 
         @requires_qapp
@@ -51,33 +53,30 @@ def requires_qapp(cls):
 
     :param cls: Class instance
     """
-    def is_test_method(name, x):
-        # Python 3 returns a functions type for methods not bound to an instance
-        return name.startswith('test') and (isfunction(x) or ismethod(x))
-
-    for name in dir(cls):
-        attr = getattr(cls, name)
-        if is_test_method(name, attr):
-            setattr(cls, name, _requires_qapp_impl(attr))
-    return cls
+    def do_nothing(self):
+      pass
 
+    orig_setUp = getattr(cls, 'setUp', do_nothing)
+    orig_tearDown = getattr(cls, 'tearDown', do_nothing)
 
-def _requires_qapp_impl(test_method):
-    """
-    Decorator for GUI test methods. Creates a QApplication before
-    executing the test.
-    :param test_method: A test method.
-    """
-    def _wrapper(self):
-        global QAPP
-        if not QAPP:
+    def setUp(self):
+        qapp = QApplication.instance()
+        if qapp is None:
             setup_library_paths()
-            QAPP = QApplication([''])
-        test_method(self)
-        QAPP.closeAllWindows()
-        gc.collect()
-
-    return _wrapper
+            self._qapp = QApplication([''])
+        else:
+            self._qapp = qapp
+        orig_setUp(self)
+
+    def tearDown(self):
+      orig_tearDown(self)
+      if self._qapp is not None:
+          self._qapp.closeAllWindows()
+          gc.collect()
+
+    cls.setUp = setUp
+    cls.tearDown = tearDown
+    return cls
 
 
 def select_item_in_tree(tree, item_label):
diff --git a/qt/python/mantidqt/utils/qt/testing/modal_tester.py b/qt/python/mantidqt/utils/qt/testing/modal_tester.py
index f7588248a440d61205f725fb82b002afd1c44507..46903979b457005d1d8cb7eef78f4325fe627d0a 100644
--- a/qt/python/mantidqt/utils/qt/testing/modal_tester.py
+++ b/qt/python/mantidqt/utils/qt/testing/modal_tester.py
@@ -39,13 +39,13 @@ import traceback
 from qtpy.QtCore import QTimer
 from qtpy.QtWidgets import QApplication
 
-QAPP = None
-
 
 class ModalTester(object):
     """
     Helper class for testing modal widgets (dialogs).
     """
+    _qapp = None
+
     def __init__(self, creator, tester):
         """
         Initialise ModalTester.
@@ -53,9 +53,11 @@ class ModalTester(object):
             A modal widget must have exec_() method.
         :param tester: A function taking a widget as its argument that does testing.
         """
-        global QAPP
-        if QAPP is None:
-            QAPP = QApplication([''])
+        qapp = QApplication.instance()
+        if qapp is None:
+            self._qapp = QApplication([' '])
+        else:
+            self._qapp = qapp
         self.creator = creator
         self.tester = tester
         self.widget = None
@@ -70,7 +72,7 @@ class ModalTester(object):
             self.widget = self.creator()
         except:
             traceback.print_exc()
-            QAPP.exit(0)
+            self._qapp.exit(0)
         if self.widget is not None:
             self.widget.exec_()
 
@@ -79,7 +81,7 @@ class ModalTester(object):
         This function runs every time in QApplication's event loop.
         Call the testing function.
         """
-        modal_widget = QAPP.activeModalWidget()
+        modal_widget = self._qapp.activeModalWidget()
         if modal_widget is not None:
             if self.widget is modal_widget:
                 try:
@@ -87,7 +89,7 @@ class ModalTester(object):
                     self.passed = True
                 except:
                     traceback.print_exc()
-                    QAPP.exit(0)
+                    self._qapp.exit(0)
             if modal_widget.isVisible():
                 modal_widget.close()
 
@@ -103,4 +105,4 @@ class ModalTester(object):
         # This calls __call__() method
         QTimer.singleShot(0, self)
         # Start the event loop
-        QAPP.exec_()
+        self._qapp.exec_()
diff --git a/qt/python/mantidqt/utils/test/test_modal_tester.py b/qt/python/mantidqt/utils/test/test_modal_tester.py
index 6cd3fb69b8b159412527307f7da4f6200fda64d0..66ec5ff868b2092b947658ad327bd18462163dd3 100644
--- a/qt/python/mantidqt/utils/test/test_modal_tester.py
+++ b/qt/python/mantidqt/utils/test/test_modal_tester.py
@@ -22,9 +22,10 @@ import unittest
 
 from qtpy.QtWidgets import QInputDialog
 
-from mantidqt.utils.qt.testing import ModalTester
+from mantidqt.utils.qt.testing import requires_qapp, ModalTester
 
 
+@requires_qapp
 class TestModalTester(unittest.TestCase):
 
     def test_pass_widget_closed(self):
diff --git a/qt/python/mantidqt/utils/test/test_qt_utils.py b/qt/python/mantidqt/utils/test/test_qt_utils.py
index 7ab77872df5385077d804161d78b42c274a9dcc3..6e9497eaf7ed1d56aa70560cfefb4ec20a89c5e8 100644
--- a/qt/python/mantidqt/utils/test/test_qt_utils.py
+++ b/qt/python/mantidqt/utils/test/test_qt_utils.py
@@ -20,26 +20,20 @@ from __future__ import (absolute_import, division, print_function,
 import unittest
 
 from qtpy.QtCore import QObject, Qt, Slot
-from qtpy.QtWidgets import QAction, QApplication, QMenu, QToolBar
+from qtpy.QtWidgets import QAction, QMenu, QToolBar
 try:
     from qtpy.QtCore import SIGNAL
     NEW_STYLE_SIGNAL = False
 except ImportError:
     NEW_STYLE_SIGNAL = True
 
+from mantidqt.utils.qt.testing import requires_qapp
 from mantidqt.utils.qt import add_actions, create_action
 
-QAPP = None
-
 
+@requires_qapp
 class CreateActionTest(unittest.TestCase):
 
-    @classmethod
-    def setUpClass(cls):
-        global QAPP
-        if QApplication.instance() is None:
-            QAPP = QApplication([''])
-
     def test_parent_and_name_only_required(self):
         class Parent(QObject):
             pass
@@ -79,14 +73,9 @@ class CreateActionTest(unittest.TestCase):
         self.assertEqual(Qt.WindowShortcut, action.shortcutContext())
 
 
+@requires_qapp
 class AddActionsTest(unittest.TestCase):
 
-    @classmethod
-    def setUpClass(cls):
-        global QAPP
-        if QApplication.instance() is None:
-            QAPP = QApplication([''])
-
     def test_add_actions_with_qmenu_target(self):
         test_act_1 = create_action(None, "Test Action 1")
         test_act_2 = create_action(None, "Test Action 2")
diff --git a/qt/python/mantidqt/widgets/test/test_algorithm_dialog.py b/qt/python/mantidqt/widgets/test/test_algorithm_dialog.py
index 3d425ab9b82b1271ead357e1d6522116dbb4c678..52121d0bd7096351c28f23c82f3467c81ae20b9a 100644
--- a/qt/python/mantidqt/widgets/test/test_algorithm_dialog.py
+++ b/qt/python/mantidqt/widgets/test/test_algorithm_dialog.py
@@ -69,3 +69,7 @@ class TestAlgorithmDialog(unittest.TestCase):
         self.assertTrue(dialog is not None)
         input_widgets = dialog.findChildren(QLineEdit)
         self.assertEqual(len(input_widgets), 3)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/qt/python/mantidqt/widgets/test/test_messagedisplay.py b/qt/python/mantidqt/widgets/test/test_messagedisplay.py
index 31dd406783d9c0f0aadd43ac9c715976eed580e6..01a2fc1287d9ef0367e118ce9a69ebe7ca346757 100644
--- a/qt/python/mantidqt/widgets/test/test_messagedisplay.py
+++ b/qt/python/mantidqt/widgets/test/test_messagedisplay.py
@@ -19,22 +19,14 @@ from __future__ import (absolute_import, division, print_function,
 
 import unittest
 
-from qtpy.QtWidgets import QApplication
-
 from mantidqt.widgets.messagedisplay import MessageDisplay
-
-QAPP = None
+from mantidqt.utils.qt.testing import requires_qapp
 
 
+@requires_qapp
 class MessageDisplayTest(unittest.TestCase):
     """Minimal testing as it is exported from C++"""
 
-    @classmethod
-    def setUpClass(cls):
-        global QAPP
-        if QApplication.instance() is None:
-            QAPP = QApplication([''])
-
     def test_widget_creation(self):
         display = MessageDisplay()
         self.assertTrue(display is not None)