source: sasview/src/sas/qtgui/Calculators/UnitTesting/DataOperationUtilityTest.py @ 7969b9c

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 7969b9c was 7fb471d, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Update for unit tests and minor functionality quirks

  • Property mode set to 100644
File size: 17.3 KB
RevLine 
[d5c5d3d]1import sys
2import time
3import numpy
4import logging
5import unittest
6from PyQt4 import QtGui
7from PyQt4 import QtCore
8from PyQt4.QtTest import QTest
9from PyQt4.QtCore import Qt
[7fb471d]10from unittest.mock import MagicMock
11from unittest.mock import patch
[d5c5d3d]12
13from twisted.internet import threads
14
15from sas.qtgui.Calculators.DataOperationUtilityPanel import DataOperationUtilityPanel
16from sas.qtgui.Utilities.GuiUtils import *
17from sas.qtgui.Plotting.PlotterData import Data1D
18from sas.qtgui.Plotting.PlotterData import Data2D
19from sas.qtgui.MainWindow.DataState import DataState
20
21if not QtGui.QApplication.instance():
22    app = QtGui.QApplication(sys.argv)
23
24BG_COLOR_ERR = 'background-color: rgb(244, 170, 164);'
25
26class DataOperationUtilityTest(unittest.TestCase):
27    """Test the ResolutionCalculator"""
28    def setUp(self):
29        """Create the ResolutionCalculator"""
30
31        class dummy_manager(object):
32            def communicator(self):
33                return Communicate()
34
35        self.widget = DataOperationUtilityPanel(dummy_manager())
36
37    def tearDown(self):
38        """Destroy the DataOperationUtility"""
39        self.widget.close()
40        self.widget = None
41
42    def testDefaults(self):
43        """Test the GUI in its default state"""
44
45        self.assertIsInstance(self.widget, QtGui.QDialog)
46
47        self.assertEqual(self.widget.windowTitle(), "Data Operation")
48        self.assertEqual(self.widget.groupBox.title(), "Data Operation "
49                                                       "[ + (add); "
50                                                       "- (subtract); "
51                                                       "* (multiply); "
52                                                       "/ (divide); "
53                                                       "| (append)]")
54        # size
55        self.assertEqual(self.widget.size().height(), 425)
56        self.assertEqual(self.widget.size().width(), 951)
57
58        # content of line edits
59        self.assertEqual(self.widget.txtNumber.text(), '1.0')
60        self.assertEqual(self.widget.txtOutputData.text(), 'MyNewDataName')
61
62        # content of comboboxes and default text / index
63        self.assertFalse(self.widget.cbData1.isEditable())
64        self.assertEqual(self.widget.cbData1.count(), 1)
65        self.assertEqual(self.widget.cbData1.currentText(),
66                         'No Data Available')
67
68        self.assertFalse(self.widget.cbData2.isEditable())
69        self.assertEqual(self.widget.cbData2.count(), 1)
70        self.assertEqual(self.widget.cbData2.currentText(),
71                         'No Data Available')
72
73        self.assertFalse(self.widget.cbOperator.isEditable())
74        self.assertEqual(self.widget.cbOperator.count(), 5)
75        self.assertEqual(self.widget.cbOperator.currentText(), '+')
76        self.assertListEqual([self.widget.cbOperator.itemText(i) for i in
77                              range(self.widget.cbOperator.count())],
78                             ['+', '-', '*', '/', '|'])
79
80        # Tooltips
81        self.assertEqual(str(self.widget.cmdCompute.toolTip()), "Generate the Data "
82                                                           "and send to Data "
83                                                           "Explorer.")
84        self.assertEqual(str(self.widget.cmdClose.toolTip()), "Close this panel.")
85        self.assertEqual(str(self.widget.cmdHelp.toolTip()),
86                         "Get help on Data Operations.")
87        self.assertEqual(self.widget.txtNumber.toolTip(), "If no Data2 loaded, "
88                                                "enter a number to be "
89                                                "applied to Data1 using "
90                                                "the operator")
91        self.assertEqual(str(self.widget.cbOperator.toolTip()), "Add: +\n"
92                                                           "Subtract: - \n"
93                                                           "Multiply: *\n"
94                                                           "Divide: /\n"
95                                                           "Append(Combine): |")
96
97        self.assertFalse(self.widget.cmdCompute.isEnabled())
98        self.assertFalse(self.widget.txtNumber.isEnabled())
99
100        self.assertIsInstance(self.widget.layoutOutput,QtGui.QHBoxLayout)
101        self.assertIsInstance(self.widget.layoutData1,QtGui.QHBoxLayout)
102        self.assertIsInstance(self.widget.layoutData2,QtGui.QHBoxLayout)
103
104        # To store input datafiles
105        self.assertIsNone(self.widget.filenames)
106        self.assertEqual(self.widget.list_data_items, [])
107        self.assertIsNone(self.widget.data1)
108        self.assertIsNone(self.widget.data2)
109        # To store the result
110        self.assertIsNone(self.widget.output)
111        self.assertFalse(self.widget.data2OK)
112        self.assertFalse(self.widget.data1OK)
113
114        self.widget.newPlot = MagicMock()
115        self.assertTrue(self.widget.newPlot.called_once())
116        self.assertTrue(self.widget.newPlot.called_once())
117        self.assertTrue(self.widget.newPlot.called_once())
118
119    def testHelp(self):
120        """ Assure help file is shown """
121        # this should not rise
122        self.widget.onHelp()
123
124    def testOnReset(self):
125        """ Test onReset function """
126        # modify gui
127        self.widget.txtNumber.setText('2.3')
128        self.widget.onReset()
129        self.assertEqual(self.widget.txtNumber.text(), '1.0')
130
131    def testOnClose(self):
132        """ test Closing window """
133        closeButton = self.widget.cmdClose
134        QTest.mouseClick(closeButton, Qt.LeftButton)
135
136
137    def testOnCompute(self):
138        """ Test onCompute function """
139
140        # define the data
141        self.widget.data1 = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
142                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
143        self.widget.data2 = 1
144
145        # mock update of plot
146        self.widget.updatePlot = MagicMock()
147
148        # enable onCompute to run (check on data type)
149        self.widget.onCheckChosenData = MagicMock(return_value=True)
150
151        # run onCompute
152        self.widget.onCompute()
153
154        # check output:
155        # x unchanged, y incremented by 1 (=data2) and updatePlot called
156        self.assertListEqual(self.widget.output.x.tolist(),
157                             self.widget.data1.x.tolist())
158        self.assertListEqual(self.widget.output.y.tolist(), [12.0, 13.0, 14.0])
159        self.assertTrue(self.widget.updatePlot.called_once())
160
161        self.widget.onPrepareOutputData = MagicMock()
162
163        self.assertTrue(self.widget.onPrepareOutputData.called_once())
164
165    def testOnSelectData1(self):
166        """ Test ComboBox for Data1 """
167        # Case 1: no data loaded
168        self.widget.onSelectData1()
169        self.assertIsNone(self.widget.data1)
170        self.assertFalse(self.widget.data1OK)
171        self.assertFalse(self.widget.cmdCompute.isEnabled())
172
173        # Case 2: data1 is a datafile
174        self.widget.filenames = MagicMock(
175            return_value={'datafile1': 'details'})
176        self.widget.updatePlot = MagicMock()
177
178        self.widget.cbData1.addItems(['Select Data', 'datafile1'])
179        self.widget.cbData1.setCurrentIndex(self.widget.cbData1.count()-1)
180        self.assertTrue(self.widget.updatePlot.called_once())
181        # Compute button disabled if data2OK == False
182        self.assertEqual(self.widget.cmdCompute.isEnabled(), self.widget.data2OK)
183
184    def testOnSelectData2(self):
185        """ Test ComboBox for Data2 """
186        self.widget.updatePlot = MagicMock()
187        # Case 1: no data loaded
188        self.widget.onSelectData2()
189        self.assertIsNone(self.widget.data2)
190        self.assertFalse(self.widget.data2OK)
191        self.assertFalse(self.widget.cmdCompute.isEnabled())
192
193        # Case 2: when empty combobox
194        self.widget.cbData2.clear()
195        self.widget.onSelectData2()
196        self.assertFalse(self.widget.txtNumber.isEnabled())
197        self.assertFalse(self.widget.cmdCompute.isEnabled())
198
199        # Case 3: when Data2 is Number
200        # add 'Number' to combobox Data2
201        self.widget.cbData2.addItem('Number')
202        # select 'Number' for cbData2
203        self.widget.cbData2.setCurrentIndex(self.widget.cbData2.count()-1)
204        self.widget.onSelectData2()
205        # check that line edit is now enabled
206        self.assertTrue(self.widget.txtNumber.isEnabled())
207        # Compute button enabled only if data1OK True
208        self.assertEqual(self.widget.cmdCompute.isEnabled(), self.widget.data1OK)
209        self.assertIsInstance(self.widget.data2, float)
210        # call updatePlot
211        self.assertTrue(self.widget.updatePlot.called_once())
212
213        # Case 4: when Data2 is a file
214        self.widget.filenames = MagicMock(
215            return_value={'datafile2': 'details'})
216        self.widget.cbData2.addItems(['Select Data', 'Number', 'datafile2'])
217        self.widget.cbData2.setCurrentIndex(self.widget.cbData2.count() - 1)
218        self.assertTrue(self.widget.updatePlot.called_once())
219        # editing of txtNumber is disabled when Data2 is a file
220        self.assertFalse(self.widget.txtNumber.isEnabled())
221        # Compute button enabled only if data1OK True
222        self.assertEqual(self.widget.cmdCompute.isEnabled(),
223                         self.widget.data1OK)
224        # call updatePlot
225        self.assertTrue(self.widget.updatePlot.called_once())
226
227    def testUpdateCombobox(self):
228        """ Test change of contents of comboboxes for Data1 and Data2 """
229        # Create input data
230        data1 = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
231                       dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
232
233        data2 = Data2D(image=[0.1] * 4,
234                       qx_data=[1.0, 2.0, 3.0, 4.0],
235                       qy_data=[10.0, 11.0, 12.0, 13.0],
236                       dqx_data=[0.1, 0.2, 0.3, 0.4],
237                       dqy_data=[0.1, 0.2, 0.3, 0.4],
238                       q_data=[1, 2, 3, 4],
239                       xmin=-1.0, xmax=5.0,
240                       ymin=-1.0, ymax=15.0,
241                       zmin=-1.0, zmax=20.0)
242
243        filenames = {'datafile2': DataState(data2),
244                                 'datafile1': DataState(data1)}
245
246        # call function
247        self.widget.updateCombobox(filenames)
248
249        # check modifications of comboboxes
250        AllItemsData1 = [self.widget.cbData1.itemText(indx)
251                         for indx in range(self.widget.cbData1.count())]
252        self.assertListEqual(AllItemsData1, ['Select Data',
253                                             'datafile2',
254                                             'datafile1'])
255
256        AllItemsData2 = [self.widget.cbData2.itemText(indx)
257                         for indx in range(self.widget.cbData2.count())]
258        self.assertListEqual(AllItemsData2,
259                             ['Select Data', 'Number',
260                              'datafile2', 'datafile1'])
261
262    def testOnSelectOperator(self):
263        """ Change GUI when operator changed """
264        self.assertEqual(self.widget.lblOperatorApplied.text(),self.widget.cbOperator.currentText())
265
266        self.widget.cbOperator.setCurrentIndex(2)
267        self.assertEqual(self.widget.lblOperatorApplied.text(),
268                         self.widget.cbOperator.currentText())
269
270    def testOnInputCoefficient(self):
271        """
272        Check input of number when a coefficient is required for operation
273        """
274        # clear input for coefficient -> error
275        self.widget.txtNumber.clear()
276        # check that color of background changed to notify error
277        self.assertIn(BG_COLOR_ERR, self.widget.txtNumber.styleSheet())
278
279
280    def testCheckChosenData(self):
281        """ Test check of data compatibility """
[0c468bf]282        # set the 2 following to True since we want to check
283        # the compatibility of dimensions
284        self.widget.data1OK = True
285        self.widget.data2OK = True
286
[d5c5d3d]287        # Case 1: incompatible dimensions
288        self.widget.data1 = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
289                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
290
291        self.widget.data2 = Data2D(image=[0.1] * 4,
292                           qx_data=[1.0, 2.0, 3.0, 4.0],
293                           qy_data=[10.0, 11.0, 12.0, 13.0],
294                           dqx_data=[0.1, 0.2, 0.3, 0.4],
295                           dqy_data=[0.1, 0.2, 0.3, 0.4],
296                           q_data=[1, 2, 3, 4],
297                           xmin=-1.0, xmax=5.0,
298                           ymin=-1.0, ymax=15.0,
299                           zmin=-1.0, zmax=20.0)
300
301        self.assertFalse(self.widget.onCheckChosenData())
302
303        # Case 2 : compatible 1 dimension
304        self.widget.data1 = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
305                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
306
307        self.widget.data2 = Data1D(x=[1.0, 2.0, 3.0], y=[1.0, 2.0, 3.0],
308                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
309
310        self.assertTrue(self.widget.onCheckChosenData())
311
312        # Case 3: compatible 2 dimension
313        self.widget.data1 = Data2D(image=[0.1] * 4,
314                                   qx_data=[1.0, 2.0, 3.0, 4.0],
315                                   qy_data=[10.0, 11.0, 12.0, 13.0],
316                                   dqx_data=[0.1, 0.2, 0.3, 0.4],
317                                   dqy_data=[0.1, 0.2, 0.3, 0.4],
318                                   q_data=[1, 2, 3, 4],
319                                   xmin=-1.0, xmax=5.0,
320                                   ymin=-1.0, ymax=15.0,
321                                   zmin=-1.0, zmax=20.0)
322
323        self.widget.data2 = Data2D(image=[0.1] * 4,
324                                   qx_data=[1.0, 2.0, 3.0, 4.0],
325                                   qy_data=[10.0, 11.0, 12.0, 13.0],
326                                   dqx_data=[0.1, 0.2, 0.3, 0.4],
327                                   dqy_data=[0.1, 0.2, 0.3, 0.4],
328                                   q_data=[1, 2, 3, 4],
329                                   xmin=-1.0, xmax=5.0,
330                                   ymin=-1.0, ymax=15.0,
331                                   zmin=-1.0, zmax=20.0)
332
333        self.assertTrue(self.widget.onCheckChosenData())
334
335        # Case 4: Different 1D
336        self.widget.data1 = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
337                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
338
339        self.widget.data2 = Data1D(x=[0.0, 1.0, 2.0], y=[1.0, 2.0, 3.0],
340                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
341
342        self.assertFalse(self.widget.onCheckChosenData())
343
344        # Case 5: Data2 is a Number
345        self.widget.cbData2.clear()
346        self.widget.cbData2.addItem('Number')
347        self.widget.cbData2.setCurrentIndex(0)
348        self.assertEqual(self.widget.cbData2.currentText(), 'Number')
349        self.assertTrue(self.widget.onCheckChosenData())
350
351    def testOnCheckOutputName(self):
352        """ Test OutputName for result of operation """
353        self.widget.txtOutputData.clear()
354        self.assertFalse(self.widget.onCheckOutputName())
355
356        self.widget.list_data_items = ['datafile1', 'datafile2']
357        self.widget.txtOutputData.setText('datafile0')
358        self.assertTrue(self.widget.onCheckOutputName())
359        self.assertIn('', self.widget.txtOutputData.styleSheet())
360
361        self.widget.txtOutputData.clear()
362        self.widget.txtOutputData.setText('datafile1')
363        self.assertFalse(self.widget.onCheckOutputName())
364        self.assertIn(BG_COLOR_ERR, self.widget.txtOutputData.styleSheet())
365
366    def testFindId(self):
367        """ Test function to find id of file in list of filenames"""
368        data_for_id = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
369                                   dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
370
371        self.widget.filenames = {'datafile2': DataState(data_for_id),
372                                 'datafile1': DataState(data_for_id)}
373
374        id_out = self.widget._findId('datafile2')
375        self.assertEqual(id_out, 'datafile2')
376
377    def testExtractData(self):
378        """
379        Test function to extract data to be computed from input filenames
380        """
381        data1 = Data1D(x=[1.0, 2.0, 3.0], y=[11.0, 12.0, 13.0],
382                       dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
383
384        data2 = Data2D(image=[0.1] * 4,
385                                   qx_data=[1.0, 2.0, 3.0, 4.0],
386                                   qy_data=[10.0, 11.0, 12.0, 13.0],
387                                   dqx_data=[0.1, 0.2, 0.3, 0.4],
388                                   dqy_data=[0.1, 0.2, 0.3, 0.4],
389                                   q_data=[1, 2, 3, 4],
390                                   xmin=-1.0, xmax=5.0,
391                                   ymin=-1.0, ymax=15.0,
392                                   zmin=-1.0, zmax=20.0)
393
394        self.widget.filenames = {'datafile2': DataState(data2),
395                                 'datafile1': DataState(data1)}
396
397        output1D = self.widget._extractData('datafile1')
398        self.assertTrue(isinstance(output1D, Data1D))
399
400        output2D = self.widget._extractData('datafile2')
401        self.assertIsInstance(output2D, Data2D)
402
403    # TODO
404    def testOnPrepareOutputData(self):
405        """ """
406        pass
407
408    # new_item = GuiUtils.createModelItemWithPlot(
409    #     QtCore.QVariant(self.output), name=self.txtOutputData.text())
410    # new_datalist_item = {str(self.txtOutputData.text()) + str(time.time()):
411    #                          self.output}
412    # self.communicator. \
413    #     updateModelFromDataOperationPanelSignal.emit(new_item,
414    #                                                  new_datalist_item)
415
416
417if __name__ == "__main__":
418    unittest.main()
Note: See TracBrowser for help on using the repository browser.