source: sasview/src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py @ b1e36a3

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 b1e36a3 was b1e36a3, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

FittingWidget? code review SASVIEW-561

  • Property mode set to 100644
File size: 15.9 KB
Line 
1import sys
2import unittest
3
4from PyQt4 import QtGui
5from PyQt4 import QtTest
6from PyQt4 import QtCore
7from mock import MagicMock
8from twisted.internet import threads
9
10# set up import paths
11import sas.qtgui.path_prepare
12
13# Local
14from sas.qtgui.GuiUtils import *
15from sas.qtgui.Perspectives.Fitting.FittingWidget import *
16from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy
17
18from sas.sasgui.guiframe.dataFitting import Data1D
19
20app = QtGui.QApplication(sys.argv)
21
22class dummy_manager(object):
23    def communicate(self):
24        return Communicate()
25
26class FittingWidgetTest(unittest.TestCase):
27    """Test the fitting widget GUI"""
28
29    def setUp(self):
30        """Create the GUI"""
31        self.widget = FittingWidget(dummy_manager())
32
33    def tearDown(self):
34        """Destroy the GUI"""
35        self.widget.close()
36        self.widget = None
37
38    def testDefaults(self):
39        """Test the GUI in its default state"""
40        self.assertIsInstance(self.widget, QtGui.QWidget)
41        self.assertEqual(self.widget.windowTitle(), "Fitting")
42        self.assertEqual(self.widget.sizePolicy().Policy(), QtGui.QSizePolicy.Fixed)
43        self.assertIsInstance(self.widget.lstParams.model(), QtGui.QStandardItemModel)
44        self.assertIsInstance(self.widget.lstPoly.model(), QtGui.QStandardItemModel)
45        self.assertIsInstance(self.widget.lstMagnetic.model(), QtGui.QStandardItemModel)
46        self.assertFalse(self.widget.cbModel.isEnabled())
47        self.assertFalse(self.widget.cbStructureFactor.isEnabled())
48        self.assertFalse(self.widget.cmdFit.isEnabled())
49        self.assertTrue(self.widget.acceptsData())
50        self.assertFalse(self.widget.data_is_loaded)
51
52    def testSelectCategory(self):
53        """
54        Test if model categories have been loaded properly
55        """
56        fittingWindow =  self.widget
57
58        #Test loading from json categories
59        category_list = fittingWindow.master_category_dict.keys()
60
61        for category in category_list:
62            self.assertNotEqual(fittingWindow.cbCategory.findText(category),-1)
63
64        #Test what is current text in the combobox
65        self.assertEqual(fittingWindow.cbCategory.currentText(), CATEGORY_DEFAULT)
66
67    def testWidgetWithData(self):
68        """
69        Test the instantiation of the widget with initial data
70        """
71        data = Data1D(x=[1,2], y=[1,2])
72        GuiUtils.dataFromItem = MagicMock(return_value=data)
73        item = QtGui.QStandardItem("test")
74
75        widget_with_data = FittingWidget(dummy_manager(), data=[item], id=3)
76
77        self.assertEqual(widget_with_data.data, data)
78        self.assertTrue(widget_with_data.data_is_loaded)
79        # self.assertTrue(widget_with_data.cmdFit.isEnabled())
80        self.assertFalse(widget_with_data.acceptsData())
81
82    def notestSelectModel(self):
83        """
84        Test if models have been loaded properly
85        :return:
86        """
87        fittingWindow =  self.widget
88
89        #Test loading from json categories
90        model_list = fittingWindow.master_category_dict["Cylinder"]
91        self.assertTrue(['cylinder', True] in model_list)
92        self.assertTrue(['core_shell_cylinder', True] in model_list)
93        self.assertTrue(['barbell', True] in model_list)
94        self.assertTrue(['core_shell_bicelle', True] in model_list)
95        self.assertTrue(['flexible_cylinder', True] in model_list)
96        self.assertTrue(['flexible_cylinder_elliptical', True] in model_list)
97        self.assertTrue(['pearl_necklace', True] in model_list)
98        self.assertTrue(['capped_cylinder', True] in model_list)
99        self.assertTrue(['elliptical_cylinder', True] in model_list)
100        self.assertTrue(['pringle', True] in model_list)
101        self.assertTrue(['hollow_cylinder', True] in model_list)
102        self.assertTrue(['core_shell_bicelle_elliptical', True] in model_list)
103        self.assertTrue(['stacked_disks', True] in model_list)
104
105        #Test for existence in combobox
106        self.assertNotEqual(fittingWindow.cbModel.findText("cylinder"),-1)
107        self.assertNotEqual(fittingWindow.cbModel.findText("core_shell_cylinder"),-1)
108        self.assertNotEqual(fittingWindow.cbModel.findText("barbell"),-1)
109        self.assertNotEqual(fittingWindow.cbModel.findText("core_shell_bicelle"),-1)
110        self.assertNotEqual(fittingWindow.cbModel.findText("flexible_cylinder"),-1)
111        self.assertNotEqual(fittingWindow.cbModel.findText("flexible_cylinder_elliptical"),-1)
112        self.assertNotEqual(fittingWindow.cbModel.findText("pearl_necklace"),-1)
113        self.assertNotEqual(fittingWindow.cbModel.findText("capped_cylinder"),-1)
114        self.assertNotEqual(fittingWindow.cbModel.findText("elliptical_cylinder"),-1)
115        self.assertNotEqual(fittingWindow.cbModel.findText("pringle"),-1)
116        self.assertNotEqual(fittingWindow.cbModel.findText("hollow_cylinder"),-1)
117        self.assertNotEqual(fittingWindow.cbModel.findText("core_shell_bicelle_elliptical"),-1)
118        self.assertNotEqual(fittingWindow.cbModel.findText("stacked_disks"),-1)
119
120
121    def testSelectPolydispersity(self):
122        """
123        Test if models have been loaded properly
124        :return:
125        """
126        fittingWindow =  self.widget
127
128        #Test loading from json categories
129        fittingWindow.SASModelToQModel("cylinder")
130        pd_index = fittingWindow.lstPoly.model().index(0,0)
131        self.assertEqual(str(pd_index.data().toString()), "Distribution of radius")
132        pd_index = fittingWindow.lstPoly.model().index(1,0)
133        self.assertEqual(str(pd_index.data().toString()), "Distribution of length")
134
135    def testSelectStructureFactor(self):
136        """
137        Test if structure factors have been loaded properly
138        :return:
139        """
140        fittingWindow =  self.widget
141
142        #Test for existence in combobox
143        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("stickyhardsphere"),-1)
144        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("hayter_msa"),-1)
145        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("squarewell"),-1)
146        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("hardsphere"),-1)
147
148        #Test what is current text in the combobox
149        self.assertTrue(fittingWindow.cbCategory.currentText(), "None")
150
151    def testSignals(self):
152        """
153        Test the widget emitted signals
154        """
155        pass
156
157    def  testSelectCategory(self):
158        """
159        Assure proper behaviour on changing category
160        """
161        self.widget.show()
162        self.assertEqual(self.widget._previous_category_index, 0)
163        # confirm the model combo contains no models
164        self.assertEqual(self.widget.cbModel.count(), 0)
165
166        # invoke the method by changing the index
167        category_index = self.widget.cbCategory.findText("Shape-Independent")
168        self.widget.cbCategory.setCurrentIndex(category_index)
169
170        # test the model combo content
171        self.assertEqual(self.widget.cbModel.count(), 29)
172
173        # Try to change back to default
174        self.widget.cbCategory.setCurrentIndex(0)
175
176        # Observe no such luck
177        self.assertEqual(self.widget.cbCategory.currentIndex(), 1)
178        self.assertEqual(self.widget.cbModel.count(), 29)
179
180        # Set the structure factor
181        structure_index=self.widget.cbCategory.findText(CATEGORY_STRUCTURE)
182        self.widget.cbCategory.setCurrentIndex(structure_index)
183        # check the enablement of controls
184        self.assertFalse(self.widget.cbModel.isEnabled())
185        self.assertTrue(self.widget.cbStructureFactor.isEnabled())
186
187    def testSelectModel(self):
188        """
189        Assure proper behaviour on changing model
190        """
191        self.widget.show()
192        # Change the category index so we have some models
193        category_index = self.widget.cbCategory.findText("Shape-Independent")
194        self.widget.cbCategory.setCurrentIndex(category_index)
195
196        # check the enablement of controls
197        self.assertTrue(self.widget.cbModel.isEnabled())
198        self.assertFalse(self.widget.cbStructureFactor.isEnabled())
199
200        # set up the model update spy
201        # spy = QtSignalSpy(self.widget._model_model, self.widget._model_model.itemChanged)
202
203        # mock the tested methods
204        self.widget.SASModelToQModel = MagicMock()
205        self.widget.createDefaultDataset = MagicMock()
206        self.widget.calculateQGridForModel = MagicMock()
207        #
208        # Now change the model
209        self.widget.cbModel.setCurrentIndex(3)
210        self.assertEqual(self.widget.cbModel.currentText(),'correlation_length')
211
212        # No data sent -> no index set, only createDefaultDataset called
213        self.assertTrue(self.widget.createDefaultDataset.called)
214        self.assertTrue(self.widget.SASModelToQModel.called)
215        self.assertFalse(self.widget.calculateQGridForModel.called)
216
217        # Let's set a dummy index on widget
218        self.widget._index = QtGui.QStandardItem()
219        # Reset the sasmodel index
220        self.widget.cbModel.setCurrentIndex(1)
221        self.assertEqual(self.widget.cbModel.currentText(),'be_polyelectrolyte')
222
223        # Observe calculateQGridForModel called
224        self.assertTrue(self.widget.calculateQGridForModel.called)
225
226    def testSelectFactor(self):
227        """
228        Assure proper behaviour on changing structure factor
229        """
230        self.widget.show()
231        # Change the category index so we have some models
232        category_index = self.widget.cbCategory.findText("Shape-Independent")
233        self.widget.cbCategory.setCurrentIndex(category_index)
234        # Change the model to one that supports structure factors
235        model_index = self.widget.cbModel.findText('fractal_core_shell')
236        self.widget.cbModel.setCurrentIndex(model_index)
237
238        # Check that the factor combo is active and the default is chosen
239        self.assertTrue(self.widget.cbStructureFactor.isEnabled())
240        self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT)
241
242        # We have this many rows in the model
243        rowcount = self.widget._model_model.rowCount()
244        #self.assertEqual(self.widget._model_model.rowCount(), 8)
245
246        # Change structure factor to something more exciting
247        structure_index = self.widget.cbStructureFactor.findText('squarewell')
248        self.widget.cbStructureFactor.setCurrentIndex(structure_index)
249
250        # We have 4 more rows now
251        self.assertEqual(self.widget._model_model.rowCount(), rowcount+4)
252
253        # Switch models
254        self.widget.cbModel.setCurrentIndex(0)
255
256        # Observe factor reset to None
257        self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT)
258
259
260        # TODO once functionality fixed
261        ## Switch category to structure factor
262        #structure_index=self.widget.cbCategory.findText(CATEGORY_STRUCTURE)
263        #self.widget.cbCategory.setCurrentIndex(structure_index)
264        ## Choose the last factor
265        #last_index = self.widget.cbStructureFactor.count()
266        #self.widget.cbStructureFactor.setCurrentIndex(last_index-1)
267
268    def testReadCategoryInfo(self):
269        """
270        Check the category file reader
271        """
272        # Tested in default checks
273        pass
274
275    def testUpdateParamsFromModel(self):
276        """
277        Checks the sasmodel parameter update from QModel items
278        """
279        # Tested in default checks
280        pass
281
282    def notestCreateTheoryIndex(self):
283        """
284        Test the data->QIndex conversion
285        """
286        # set up the model update spy
287        spy = QtSignalSpy(self.widget._model_model, self.widget.communicate.updateTheoryFromPerspectiveSignal)
288
289        self.widget.show()
290        # Change the category index so we have some models
291        self.widget.cbCategory.setCurrentIndex(1)
292
293        # Create the index
294        self.widget.createTheoryIndex()
295
296        # Check the signal sent
297        print spy
298
299        # Check the index
300
301    def testCalculateQGridForModel(self):
302        """
303        Check that the fitting 1D data object is ready
304        """
305        # Mock the thread creation
306        threads.deferToThread = MagicMock()
307        # Call the tested method
308        self.widget.calculateQGridForModel()
309        # Test the mock
310        self.assertTrue(threads.deferToThread.called)
311        self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute")
312
313    def testComplete1D(self):
314        """
315        Check that a new 1D plot is generated
316        """
317        # TODO when chisqr method coded
318        pass
319
320    def testComplete2D(self):
321        """
322        Check that a new 2D plot is generated
323        """
324        # TODO when chisqr method coded
325        pass
326
327    def testSetPolyModel(self):
328        """
329        Test the polydispersity model setup
330        """
331        self.widget.show()
332        # Change the category index so we have a model with no poly
333        category_index = self.widget.cbCategory.findText("Shape-Independent")
334        self.widget.cbCategory.setCurrentIndex(category_index)
335        # Check the poly model
336        self.assertEqual(self.widget._poly_model.rowCount(), 0)
337        self.assertEqual(self.widget._poly_model.columnCount(), 0)
338
339        # Change the category index so we have a model available
340        self.widget.cbCategory.setCurrentIndex(2)
341
342        # Check the poly model
343        self.assertEqual(self.widget._poly_model.rowCount(), 3)
344        self.assertEqual(self.widget._poly_model.columnCount(), 7)
345
346        # Test the header
347        self.assertEqual(self.widget.lstPoly.horizontalHeader().count(), 7)
348        self.assertFalse(self.widget.lstPoly.horizontalHeader().stretchLastSection())
349
350        # Test presence of comboboxes in last column
351        for row in xrange(self.widget._poly_model.rowCount()):
352            func_index = self.widget._poly_model.index(row, 6)
353            self.assertTrue(isinstance(self.widget.lstPoly.indexWidget(func_index), QtGui.QComboBox))
354            self.assertIn('Distribution of', self.widget._poly_model.item(row, 0).text())
355
356    def testSetMagneticModel(self):
357        """
358        Test the magnetic model setup
359        """
360        self.widget.show()
361        # Change the category index so we have a model available
362        category_index = self.widget.cbCategory.findText("Shapes")
363        self.widget.cbCategory.setCurrentIndex(category_index)
364
365        # Check the magnetic model
366        self.assertEqual(self.widget._magnet_model.rowCount(), 9)
367        self.assertEqual(self.widget._magnet_model.columnCount(), 5)
368
369        # Test the header
370        self.assertEqual(self.widget.lstMagnetic.horizontalHeader().count(), 5)
371        self.assertFalse(self.widget.lstMagnetic.horizontalHeader().stretchLastSection())
372
373        # Test rows
374        for row in xrange(self.widget._magnet_model.rowCount()):
375            func_index = self.widget._magnet_model.index(row, 0)
376            self.assertIn(':', self.widget._magnet_model.item(row, 0).text())
377
378
379    def testAddExtraShells(self):
380        """
381        Test how the extra shells are presented
382        """
383        pass
384
385    def testModifyShellsInList(self):
386        """
387        Test the additional rows added by modifying the shells combobox
388        """
389        self.widget.show()
390        # Change the model to multi shell
391        category_index = self.widget.cbCategory.findText("Shapes")
392        self.widget.cbCategory.setCurrentIndex(category_index)
393        model_index = self.widget.cbModel.findText("core_multi_shell")
394        self.widget.cbModel.setCurrentIndex(model_index)
395
396        # Assure we have the combobox available
397        last_row = self.widget._last_model_row
398        func_index = self.widget._model_model.index(last_row-1, 1)
399        self.assertIsInstance(self.widget.lstParams.indexWidget(func_index), QtGui.QComboBox)
400
401        # Change the combo box index
402        self.widget.lstParams.indexWidget(func_index).setCurrentIndex(3)
403
404        # Check that the number of rows increased
405        more_rows = self.widget._model_model.rowCount() - last_row
406        self.assertEqual(more_rows, 6) # 6 new rows: 2 params per index
407
408        # Back to 0
409        self.widget.lstParams.indexWidget(func_index).setCurrentIndex(0)
410        self.assertEqual(self.widget._model_model.rowCount(), last_row)
411
412
413if __name__ == "__main__":
414    unittest.main()
Note: See TracBrowser for help on using the repository browser.