Index: src/sas/qtgui/UnitTesting/DataExplorerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
@@ -0,0 +1,173 @@
+import sys
+import unittest
+
+from PyQt4.QtGui import *
+from PyQt4.QtTest import QTest
+from PyQt4.QtCore import *
+from mock import MagicMock
+
+# Local
+from sas.sasgui.guiframe.dataFitting import Data1D
+from DataExplorer import DataExplorerWindow
+from GuiManager import GuiManager
+from GuiUtils import *
+from UnitTesting.TestUtils import QtSignalSpy
+
+app = QApplication(sys.argv)
+
+class DataExplorerTest(unittest.TestCase):
+    '''Test the Data Explorer GUI'''
+    def setUp(self):
+        '''Create the GUI'''
+        class dummy_manager(object):
+            def communicator(self):
+                return Communicate()
+
+        self.form = DataExplorerWindow(None, dummy_manager())
+
+    def tearDown(self):
+        '''Destroy the GUI'''
+        self.form.close()
+        self.form = None
+
+    def testDefaults(self):
+        '''Test the GUI in its default state'''
+        self.assertIsInstance(self.form, QTabWidget)
+        self.assertIsInstance(self.form.treeView, QTreeView)
+        self.assertIsInstance(self.form.listView, QListView)
+        self.assertEqual(self.form.count(), 2)
+
+        self.assertEqual(self.form.cmdLoad.text(), "Load")
+        self.assertEqual(self.form.cmdDelete.text(), "Delete")
+        self.assertEqual(self.form.cmdSendTo.text(), "Send to")
+        self.assertEqual(self.form.chkBatch.text(), "Batch mode")
+        self.assertFalse(self.form.chkBatch.isChecked())
+
+        self.assertEqual(self.form.cbSelect.count(), 6)
+
+        # Class is in the default state even without pressing OK
+        self.assertEqual(self.form.treeView.model().rowCount(), 0)
+        self.assertEqual(self.form.treeView.model().columnCount(), 0)
+        self.assertEqual(self.form.model.rowCount(), 0)
+        self.assertEqual(self.form.model.columnCount(), 0)
+        
+    def testLoadButton(self):
+        loadButton = self.form.cmdLoad
+
+        # Mock the system file open method
+        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=None)
+
+        # Click on the Load button
+        QTest.mouseClick(loadButton, Qt.LeftButton)
+
+        # Test the getOpenFileName() dialog called once
+        self.assertTrue(QtGui.QFileDialog.getOpenFileName.called)
+        QtGui.QFileDialog.getOpenFileName.assert_called_once()
+
+    def testDeleteButton(self):
+
+        deleteButton = self.form.cmdDelete
+
+        # Mock the confirmation dialog with return=Yes
+
+        # Populate the model
+
+        # Assure the checkbox is on
+
+        # Click on the delete  button
+        QTest.mouseClick(deleteButton, Qt.LeftButton)
+
+        # Test the warning dialog called once
+        # self.assertTrue(QtGui.QFileDialog.getOpenFileName.called)
+
+        # Assure the model contains no items
+
+    def testSendToButton(self):        
+        sendToButton = self.form.cmdSendTo
+
+        # Mock the current perspective set_data method
+
+        # Populate the model
+
+        # Assure the checkbox is on
+
+        # Click on the Send To  button
+        QTest.mouseClick(sendToButton, Qt.LeftButton)
+
+        # Test the set_data method called once
+        # self.assertTrue(QtGui.QFileDialog.getOpenFileName.called)
+
+        # Assure the model contains no items
+
+    def testReadData(self):
+        """
+        Test the readData() method
+        """
+        filename = ["cyl_400_20.txt"]
+        self.form.manager.add_data = MagicMock()
+
+        # Initialize signal spy instances
+        spy_status_update = QtSignalSpy(self.form, self.form.communicate.statusBarUpdateSignal)
+        spy_data_received = QtSignalSpy(self.form, self.form.communicate.fileDataReceivedSignal)
+
+        # Read in the file
+        self.form.readData(filename)
+
+        # Expected two status bar updates
+        self.assertEqual(spy_status_update.count(), 2)
+        self.assertIn(filename[0], str(spy_status_update.called()[0]['args'][0]))
+        self.assertIn("Loading Data Complete", str(spy_status_update.called()[1]['args'][0]))
+
+        # Expect one Data Received signal
+        self.assertEqual(spy_data_received.count(), 1)
+
+        # Assure returned dictionary has correct data
+        # We don't know the data ID, so need to iterate over dict
+        data_dict = spy_data_received.called()[0]['args'][0]
+        for data_key, data_value in data_dict.iteritems():
+            self.assertIsInstance(data_value, Data1D)
+
+        # Check that the model contains the item
+        self.assertEqual(self.form.model.rowCount(), 1)
+        self.assertEqual(self.form.model.columnCount(), 1)
+
+        # The 0th item header should be the name of the file
+        model_item = self.form.model.index(0,0)
+        model_name = str(self.form.model.data(model_item).toString())
+        self.assertEqual(model_name, filename[0])
+
+        # Assure add_data on data_manager was called (last call)
+        self.assertTrue(self.form.manager.add_data.called)
+
+    def testGetWList(self):
+        """
+        """
+        list = self.form.getWlist()
+        defaults = 'All (*.*);;canSAS files (*.xml);;SESANS files' +\
+            ' (*.ses);;ASCII files (*.txt);;IGOR 2D files (*.asc);;' +\
+            'IGOR/DAT 2D Q_map files (*.dat);;IGOR 1D files (*.abs);;'+\
+            'HFIR 1D files (*.d1d);;DANSE files (*.sans);;NXS files (*.nxs)'
+        self.assertEqual(defaults, list)
+
+    def testLoadComplete(self):
+        """
+        """
+        # Initialize signal spy instances        
+        spy_status_update = QtSignalSpy(self.form, self.form.communicate.statusBarUpdateSignal)
+        spy_data_received = QtSignalSpy(self.form, self.form.communicate.fileDataReceivedSignal)
+
+        # Need an empty Data1D object
+        mockData = Data1D()
+
+        # Call the tested method
+        self.form.loadComplete({"a":mockData}, message="test message")
+
+        # test the signals 
+        self.assertEqual(spy_status_update.count(), 1)
+        self.assertIn("message", str(spy_status_update.called()[0]['args'][0]))
+        self.assertEqual(spy_data_received.count(), 1)
+
+        # The data_manager update is going away, so don't bother testing
+       
+if __name__ == "__main__":
+    unittest.main()
Index: src/sas/qtgui/UnitTesting/InvariantTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/InvariantTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ src/sas/qtgui/UnitTesting/InvariantTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
@@ -0,0 +1,32 @@
+import sys
+import unittest
+
+from PyQt4.QtGui import QApplication
+from PyQt4.QtTest import QTest
+from PyQt4.QtCore import Qt
+from new_invariant import InvariantWindow
+
+app = QApplication(sys.argv)
+
+class InvariantTest(unittest.TestCase):
+    '''Test the invariant GUI'''
+    def setUp(self):
+        '''Create the GUI'''
+        self.form = InvariantWindow()
+
+    def test_defaults(self):
+        '''Test the GUI in its default state'''
+        self.assertEqual(self.form.lineEdit_4.text(), "0.0")
+        self.assertEqual(self.form.lineEdit_6.text(), "1.0")
+        self.assertEqual(self.form.pushButton.text(), "Calculate")
+
+        # Class is in the default state even without pressing OK
+        self.assertEqual(self.form._background, 0.0)
+        self.assertEqual(self.form._scale, 1.0)
+        
+        # Push OK with the left mouse button
+        helpButton = self.form.pushButton_3
+        QTest.mouseClick(helpButton, Qt.LeftButton)
+
+if __name__ == "__main__":
+    unittest.main()
Index: src/sas/qtgui/UnitTesting/MainWindowTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/MainWindowTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ src/sas/qtgui/UnitTesting/MainWindowTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
@@ -0,0 +1,39 @@
+import sys
+import unittest
+
+from PyQt4.QtGui import *
+from PyQt4.QtTest import QTest
+from PyQt4.QtCore import *
+from mock import MagicMock
+
+# Local
+from MainWindow import MainSasViewWindow
+from MainWindow import SplashScreen
+
+app = QApplication(sys.argv)
+
+class MainWindowTest(unittest.TestCase):
+    '''Test the Main Window GUI'''
+    def setUp(self):
+        '''Create the GUI'''
+
+        self.widget = MainSasViewWindow(None)
+
+    def tearDown(self):
+        '''Destroy the GUI'''
+        self.widget.close()
+        self.widget = None
+
+    def testDefaults(self):
+        '''Test the GUI in its default state'''
+        self.assertIsInstance(self.widget, QMainWindow)
+        self.assertIsInstance(self.widget.centralWidget(), QWorkspace)
+        
+    def testSplashScreen(self):
+        """
+        """
+        splash = SplashScreen()
+        self.assertIsInstance(splash, QSplashScreen)
+       
+if __name__ == "__main__":
+    unittest.main()
Index: src/sas/qtgui/UnitTesting/TestUtils.py
===================================================================
--- src/sas/qtgui/UnitTesting/TestUtils.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ src/sas/qtgui/UnitTesting/TestUtils.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
@@ -0,0 +1,54 @@
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from PyQt4.QtTest import *
+
+class QtSignalSpy(QObject):
+    """
+    Helper class for testing Qt signals.
+    """
+    def __init__(self, widget, signal, parent=None):
+        """
+        """
+        super(QtSignalSpy, self).__init__(parent)
+
+        self._connector = {}
+        self._count = 0
+        self._signal = [None, None]
+
+        # Assign our own slot to the emitted signal
+        if isinstance(signal, pyqtBoundSignal):
+            signal.connect(self.slot)
+        elif hasattr(widget, signal):
+            getattr(widget, signal).connect(self.slot)
+        else:
+            widget.signal.connect(slot)
+
+    def slot(self, *args, **kwargs):
+        """
+        Record emitted signal.
+        """
+        self._connector[self._count] = {
+            'args'   : args,
+            'kwargs' : kwargs,
+            }
+
+        self._count += 1
+        self._signal = [args, kwargs]
+
+    def signal(self, index=None):
+        """
+        """
+        if index == None:
+            return self._signal
+        else:
+            return self._signal[index]
+
+    def count(self):
+        """
+        """
+        return self._count
+
+    def called(self):
+        """
+        """
+        return self._connector
