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

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 a14a2b0 was a14a2b0, checked in by celinedurniak <celine.durniak@…>, 7 years ago

Fixed bug with non updated value of fitted parameter in new GUI

  • Property mode set to 100644
File size: 32.6 KB
Line 
1import sys
2import unittest
3import time
4
5from PyQt4 import QtGui
6from PyQt4 import QtTest
7from PyQt4 import QtCore
8from mock import MagicMock
9from twisted.internet import threads
10
11# set up import paths
12import sas.qtgui.path_prepare
13
14# Local
15from sas.qtgui.Utilities.GuiUtils import *
16from sas.qtgui.Perspectives.Fitting.FittingWidget import *
17from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy
18
19from sas.qtgui.Plotting.PlotterData import Data1D
20from sas.qtgui.Plotting.PlotterData import Data2D
21
22if not QtGui.QApplication.instance():
23    app = QtGui.QApplication(sys.argv)
24
25class dummy_manager(object):
26    HELP_DIRECTORY_LOCATION = "html"
27    communicate = Communicate()
28
29class FittingWidgetTest(unittest.TestCase):
30    """Test the fitting widget GUI"""
31
32    def setUp(self):
33        """Create the GUI"""
34        self.widget = FittingWidget(dummy_manager())
35
36    def tearDown(self):
37        """Destroy the GUI"""
38        self.widget.close()
39        del self.widget
40
41    def testDefaults(self):
42        """Test the GUI in its default state"""
43        self.assertIsInstance(self.widget, QtGui.QWidget)
44        self.assertEqual(self.widget.windowTitle(), "Fitting")
45        self.assertEqual(self.widget.sizePolicy().Policy(), QtGui.QSizePolicy.Fixed)
46        self.assertIsInstance(self.widget.lstParams.model(), QtGui.QStandardItemModel)
47        self.assertIsInstance(self.widget.lstPoly.model(), QtGui.QStandardItemModel)
48        self.assertIsInstance(self.widget.lstMagnetic.model(), QtGui.QStandardItemModel)
49        self.assertFalse(self.widget.cbModel.isEnabled())
50        self.assertFalse(self.widget.cbStructureFactor.isEnabled())
51        self.assertFalse(self.widget.cmdFit.isEnabled())
52        self.assertTrue(self.widget.acceptsData())
53        self.assertFalse(self.widget.data_is_loaded)
54
55    def testSelectCategoryDefault(self):
56        """
57        Test if model categories have been loaded properly
58        """
59        fittingWindow =  self.widget
60
61        #Test loading from json categories
62        category_list = fittingWindow.master_category_dict.keys()
63
64        for category in category_list:
65            self.assertNotEqual(fittingWindow.cbCategory.findText(category),-1)
66
67        #Test what is current text in the combobox
68        self.assertEqual(fittingWindow.cbCategory.currentText(), CATEGORY_DEFAULT)
69
70    def testWidgetWithData(self):
71        """
72        Test the instantiation of the widget with initial data
73        """
74        data = Data1D(x=[1,2], y=[1,2])
75        GuiUtils.dataFromItem = MagicMock(return_value=data)
76        item = QtGui.QStandardItem("test")
77
78        widget_with_data = FittingWidget(dummy_manager(), data=item, tab_id=3)
79
80        self.assertEqual(widget_with_data.data, data)
81        self.assertTrue(widget_with_data.data_is_loaded)
82        # self.assertTrue(widget_with_data.cmdFit.isEnabled())
83        self.assertFalse(widget_with_data.acceptsData())
84
85    def testSelectPolydispersity(self):
86        """
87        Test if models have been loaded properly
88        """
89        fittingWindow =  self.widget
90
91        self.assertIsInstance(fittingWindow.lstPoly.itemDelegate(), QtGui.QStyledItemDelegate)
92        #Test loading from json categories
93        fittingWindow.SASModelToQModel("cylinder")
94        pd_index = fittingWindow.lstPoly.model().index(0,0)
95        self.assertEqual(str(pd_index.data().toString()), "Distribution of radius")
96        pd_index = fittingWindow.lstPoly.model().index(1,0)
97        self.assertEqual(str(pd_index.data().toString()), "Distribution of length")
98
99        # test the delegate a bit
100        delegate = fittingWindow.lstPoly.itemDelegate()
101        self.assertEqual(len(delegate.POLYDISPERSE_FUNCTIONS), 5)
102        self.assertEqual(delegate.editableParameters(), [2, 3, 4, 5])
103        self.assertEqual(delegate.poly_function, 6)
104        self.assertIsInstance(delegate.combo_updated, QtCore.pyqtBoundSignal)
105
106    def testSelectStructureFactor(self):
107        """
108        Test if structure factors have been loaded properly
109        """
110        fittingWindow =  self.widget
111
112        #Test for existence in combobox
113        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("stickyhardsphere"),-1)
114        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("hayter_msa"),-1)
115        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("squarewell"),-1)
116        self.assertNotEqual(fittingWindow.cbStructureFactor.findText("hardsphere"),-1)
117
118        #Test what is current text in the combobox
119        self.assertTrue(fittingWindow.cbCategory.currentText(), "None")
120
121    def testSignals(self):
122        """
123        Test the widget emitted signals
124        """
125        pass
126
127    def testSelectCategory(self):
128        """
129        Assure proper behaviour on changing category
130        """
131        self.widget.show()
132        self.assertEqual(self.widget._previous_category_index, 0)
133        # confirm the model combo contains no models
134        self.assertEqual(self.widget.cbModel.count(), 0)
135
136        # invoke the method by changing the index
137        category_index = self.widget.cbCategory.findText("Shape Independent")
138        self.widget.cbCategory.setCurrentIndex(category_index)
139
140        # test the model combo content
141        self.assertEqual(self.widget.cbModel.count(), 29)
142
143        # Try to change back to default
144        self.widget.cbCategory.setCurrentIndex(0)
145
146        # Observe no such luck
147        self.assertEqual(self.widget.cbCategory.currentIndex(), 6)
148        self.assertEqual(self.widget.cbModel.count(), 29)
149
150        # Set the structure factor
151        structure_index=self.widget.cbCategory.findText(CATEGORY_STRUCTURE)
152        self.widget.cbCategory.setCurrentIndex(structure_index)
153        # check the enablement of controls
154        self.assertFalse(self.widget.cbModel.isEnabled())
155        self.assertTrue(self.widget.cbStructureFactor.isEnabled())
156
157    def testSelectModel(self):
158        """
159        Assure proper behaviour on changing model
160        """
161        self.widget.show()
162        # Change the category index so we have some models
163        category_index = self.widget.cbCategory.findText("Shape Independent")
164        self.widget.cbCategory.setCurrentIndex(category_index)
165
166        # check the enablement of controls
167        self.assertTrue(self.widget.cbModel.isEnabled())
168        self.assertFalse(self.widget.cbStructureFactor.isEnabled())
169
170        # set up the model update spy
171        # spy = QtSignalSpy(self.widget._model_model, self.widget._model_model.itemChanged)
172
173        # mock the tested methods
174        self.widget.SASModelToQModel = MagicMock()
175        self.widget.createDefaultDataset = MagicMock()
176        self.widget.calculateQGridForModel = MagicMock()
177        #
178        # Now change the model
179        self.widget.cbModel.setCurrentIndex(3)
180        self.assertEqual(self.widget.cbModel.currentText(),'dab')
181
182        # No data sent -> no index set, only createDefaultDataset called
183        self.assertTrue(self.widget.createDefaultDataset.called)
184        self.assertTrue(self.widget.SASModelToQModel.called)
185        self.assertFalse(self.widget.calculateQGridForModel.called)
186
187        # Let's tell the widget that data has been loaded
188        self.widget.data_is_loaded = True
189        # Reset the sasmodel index
190        self.widget.cbModel.setCurrentIndex(1)
191        self.assertEqual(self.widget.cbModel.currentText(),'broad_peak')
192
193        # Observe calculateQGridForModel called
194        self.assertTrue(self.widget.calculateQGridForModel.called)
195
196    def testSelectFactor(self):
197        """
198        Assure proper behaviour on changing structure factor
199        """
200        self.widget.show()
201        # Change the category index so we have some models
202        category_index = self.widget.cbCategory.findText("Shape Independent")
203        self.widget.cbCategory.setCurrentIndex(category_index)
204        # Change the model to one that supports structure factors
205        model_index = self.widget.cbModel.findText('fractal_core_shell')
206        self.widget.cbModel.setCurrentIndex(model_index)
207
208        # Check that the factor combo is active and the default is chosen
209        self.assertTrue(self.widget.cbStructureFactor.isEnabled())
210        self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT)
211
212        # We have this many rows in the model
213        rowcount = self.widget._model_model.rowCount()
214        #self.assertEqual(self.widget._model_model.rowCount(), 8)
215
216        # Change structure factor to something more exciting
217        structure_index = self.widget.cbStructureFactor.findText('squarewell')
218        self.widget.cbStructureFactor.setCurrentIndex(structure_index)
219
220        # We have 4 more rows now
221        self.assertEqual(self.widget._model_model.rowCount(), rowcount+4)
222
223        # Switch models
224        self.widget.cbModel.setCurrentIndex(0)
225
226        # Observe factor reset to None
227        self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT)
228
229        # Switch category to structure factor
230        structure_index=self.widget.cbCategory.findText(CATEGORY_STRUCTURE)
231        self.widget.cbCategory.setCurrentIndex(structure_index)
232        # Observe the correct enablement
233        self.assertTrue(self.widget.cbStructureFactor.isEnabled())
234        self.assertFalse(self.widget.cbModel.isEnabled())
235        self.assertEqual(self.widget._model_model.rowCount(), 0)
236
237        # Choose the last factor
238        last_index = self.widget.cbStructureFactor.count()
239        self.widget.cbStructureFactor.setCurrentIndex(last_index-1)
240        # Do we have all the rows?
241        self.assertEqual(self.widget._model_model.rowCount(), 4)
242
243        # Are the command buttons properly enabled?
244        self.assertTrue(self.widget.cmdPlot.isEnabled())
245        self.assertFalse(self.widget.cmdFit.isEnabled())
246
247    def testReadCategoryInfo(self):
248        """
249        Check the category file reader
250        """
251        # Tested in default checks
252        pass
253
254    def testUpdateParamsFromModel(self):
255        """
256        Checks the sasmodel parameter update from QModel items
257        """
258        # Tested in default checks
259        pass
260
261    def testCreateTheoryIndex(self):
262        """
263        Test the data->QIndex conversion
264        """
265        # set up the model update spy
266        spy = QtSignalSpy(self.widget._model_model, self.widget.communicate.updateTheoryFromPerspectiveSignal)
267
268        self.widget.show()
269        # Change the category index so we have some models
270        self.widget.cbCategory.setCurrentIndex(1)
271
272        # Create the index
273        self.widget.createTheoryIndex(Data1D(x=[1,2], y=[1,2]))
274
275        # Make sure the signal has been emitted
276        self.assertEqual(spy.count(), 1)
277
278        # Check the argument type
279        self.assertIsInstance(spy.called()[0]['args'][0], QtGui.QStandardItem)
280
281    def testCalculateQGridForModel(self):
282        """
283        Check that the fitting 1D data object is ready
284        """
285        # Mock the thread creation
286        threads.deferToThread = MagicMock()
287        # Model for theory
288        self.widget.SASModelToQModel("cylinder")
289        # Call the tested method
290        self.widget.calculateQGridForModel()
291        time.sleep(1)
292        # Test the mock
293        self.assertTrue(threads.deferToThread.called)
294        self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute")
295
296    def testCalculateResiduals(self):
297        """
298        Check that the residuals are calculated and plots updated
299        """
300        test_data = Data1D(x=[1,2], y=[1,2])
301
302        # Model for theory
303        self.widget.SASModelToQModel("cylinder")
304        # Invoke the tested method
305        self.widget.calculateResiduals(test_data)
306        # Check the Chi2 value - should be undetermined
307        self.assertEqual(self.widget.lblChi2Value.text(), '---')
308
309        # Force same data into logic
310        self.widget.logic.data = test_data
311        self.widget.calculateResiduals(test_data)
312        # Now, the difference is 0, as data is the same
313        self.assertEqual(self.widget.lblChi2Value.text(), '0')
314
315        # Change data
316        test_data_2 = Data1D(x=[1,2], y=[2.1,3.49])
317        self.widget.logic.data = test_data_2
318        self.widget.calculateResiduals(test_data)
319        # Now, the difference is non-zero
320        self.assertEqual(float(self.widget.lblChi2Value.text()), 1.7151)
321
322    def testSetPolyModel(self):
323        """
324        Test the polydispersity model setup
325        """
326        self.widget.show()
327        # Change the category index so we have a model with no poly
328        category_index = self.widget.cbCategory.findText("Shape Independent")
329        self.widget.cbCategory.setCurrentIndex(category_index)
330        # Check the poly model
331        self.assertEqual(self.widget._poly_model.rowCount(), 0)
332        self.assertEqual(self.widget._poly_model.columnCount(), 0)
333
334        # Change the category index so we have a model available
335        self.widget.cbCategory.setCurrentIndex(2)
336
337        # Check the poly model
338        self.assertEqual(self.widget._poly_model.rowCount(), 4)
339        self.assertEqual(self.widget._poly_model.columnCount(), 8)
340
341        # Test the header
342        self.assertEqual(self.widget.lstPoly.horizontalHeader().count(), 8)
343        self.assertFalse(self.widget.lstPoly.horizontalHeader().stretchLastSection())
344
345        # Test presence of comboboxes in last column
346        for row in xrange(self.widget._poly_model.rowCount()):
347            func_index = self.widget._poly_model.index(row, 6)
348            self.assertTrue(isinstance(self.widget.lstPoly.indexWidget(func_index), QtGui.QComboBox))
349            self.assertIn('Distribution of', self.widget._poly_model.item(row, 0).text())
350        #self.widget.close()
351
352    def testPolyModelChange(self):
353        """
354        Polydispersity model changed - test all possible scenarios
355        """
356        self.widget.show()
357        # Change the category index so we have a model with polydisp
358        category_index = self.widget.cbCategory.findText("Cylinder")
359        self.widget.cbCategory.setCurrentIndex(category_index)
360
361        # click on a poly parameter checkbox
362        index = self.widget._poly_model.index(0,0)
363        # Set the checbox
364        self.widget._poly_model.item(0,0).setCheckState(2)
365        # Assure the parameter is added
366        self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width'])
367
368        # Add another parameter
369        self.widget._poly_model.item(2,0).setCheckState(2)
370        # Assure the parameters are added
371        self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width', 'length.width'])
372
373        # Change the min/max values
374        self.assertEqual(self.widget.kernel_module.details['radius_bell'][1], 0.0)
375        self.widget._poly_model.item(0,2).setText("1.0")
376        self.assertEqual(self.widget.kernel_module.details['radius_bell'][1], 1.0)
377
378        # Change the number of points
379        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 35)
380        self.widget._poly_model.item(0,4).setText("22")
381        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 22)
382        # try something stupid
383        self.widget._poly_model.item(0,4).setText("butt")
384        # see that this didn't annoy the control at all
385        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 22)
386
387        # Change the number of sigmas
388        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 3)
389        self.widget._poly_model.item(0,5).setText("222")
390        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 222)
391        # try something stupid again
392        self.widget._poly_model.item(0,4).setText("beer")
393        # no efect
394        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 222)
395
396    def testOnPolyComboIndexChange(self):
397        """
398        Test the slot method for polydisp. combo box index change
399        """
400        self.widget.show()
401        # Change the category index so we have a model with polydisp
402        category_index = self.widget.cbCategory.findText("Cylinder")
403        self.widget.cbCategory.setCurrentIndex(category_index)
404
405        # call method with default settings
406        self.widget.onPolyComboIndexChange('gaussian', 0)
407        # check values
408        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 35)
409        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 3)
410        # Change the index
411        self.widget.onPolyComboIndexChange('rectangle', 0)
412        # check values
413        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 35)
414        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 1.70325)
415        # Change the index
416        self.widget.onPolyComboIndexChange('lognormal', 0)
417        # check values
418        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 80)
419        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 8)
420        # Change the index
421        self.widget.onPolyComboIndexChange('schulz', 0)
422        # check values
423        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 80)
424        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 8)
425
426        # mock up file load
427        self.widget.loadPolydispArray = MagicMock()
428        # Change to 'array'
429        self.widget.onPolyComboIndexChange('array', 0)
430        # See the mock fire
431        self.assertTrue(self.widget.loadPolydispArray.called)
432
433    def testLoadPolydispArray(self):
434        """
435        Test opening of the load file dialog for 'array' polydisp. function
436        """
437        filename = os.path.join("UnitTesting", "testdata_noexist.txt")
438        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
439        self.widget.show()
440        # Change the category index so we have a model with polydisp
441        category_index = self.widget.cbCategory.findText("Cylinder")
442        self.widget.cbCategory.setCurrentIndex(category_index)
443
444        self.widget.onPolyComboIndexChange('array', 0)
445        # check values - unchanged since the file doesn't exist
446        self.assertTrue(self.widget._poly_model.item(0, 1).isEnabled())
447        with self.assertRaises(AttributeError):
448            self.widget.disp_model()
449
450        # good file
451        filename = os.path.join("UnitTesting", "testdata.txt")
452        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
453
454        self.widget.onPolyComboIndexChange('array', 0)
455        # check values - disabled control, present weights
456        self.assertFalse(self.widget._poly_model.item(0, 1).isEnabled())
457        self.assertEqual(self.widget.disp_model.weights[0], 2.83954)
458        self.assertEqual(len(self.widget.disp_model.weights), 19)
459        self.assertEqual(len(self.widget.disp_model.values), 19)
460        self.assertEqual(self.widget.disp_model.values[0], 0.0)
461        self.assertEqual(self.widget.disp_model.values[18], 3.67347)
462
463    def testSetMagneticModel(self):
464        """
465        Test the magnetic model setup
466        """
467        self.widget.show()
468        # Change the category index so we have a model available
469        category_index = self.widget.cbCategory.findText("Sphere")
470        self.widget.cbCategory.setCurrentIndex(category_index)
471
472        # Check the magnetic model
473        self.assertEqual(self.widget._magnet_model.rowCount(), 9)
474        self.assertEqual(self.widget._magnet_model.columnCount(), 5)
475
476        # Test the header
477        self.assertEqual(self.widget.lstMagnetic.horizontalHeader().count(), 5)
478        self.assertFalse(self.widget.lstMagnetic.horizontalHeader().stretchLastSection())
479
480        # Test rows
481        for row in xrange(self.widget._magnet_model.rowCount()):
482            func_index = self.widget._magnet_model.index(row, 0)
483            self.assertIn(':', self.widget._magnet_model.item(row, 0).text())
484
485
486    def testAddExtraShells(self):
487        """
488        Test how the extra shells are presented
489        """
490        pass
491
492    def testModifyShellsInList(self):
493        """
494        Test the additional rows added by modifying the shells combobox
495        """
496        self.widget.show()
497        # Change the model to multi shell
498        category_index = self.widget.cbCategory.findText("Sphere")
499        self.widget.cbCategory.setCurrentIndex(category_index)
500        model_index = self.widget.cbModel.findText("core_multi_shell")
501        self.widget.cbModel.setCurrentIndex(model_index)
502
503        # Assure we have the combobox available
504        last_row = self.widget._last_model_row
505        func_index = self.widget._model_model.index(last_row-1, 1)
506        self.assertIsInstance(self.widget.lstParams.indexWidget(func_index), QtGui.QComboBox)
507
508        # Change the combo box index
509        self.widget.lstParams.indexWidget(func_index).setCurrentIndex(3)
510
511        # Check that the number of rows increased
512        more_rows = self.widget._model_model.rowCount() - last_row
513        self.assertEqual(more_rows, 6) # 6 new rows: 2 params per index
514
515        # Back to 0
516        self.widget.lstParams.indexWidget(func_index).setCurrentIndex(0)
517        self.assertEqual(self.widget._model_model.rowCount(), last_row)
518
519    def testPlotTheory(self):
520        """
521        See that theory item can produce a chart
522        """
523        # By default, the compute/plot button is disabled
524        self.assertFalse(self.widget.cmdPlot.isEnabled())
525        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot')
526
527        # Assign a model
528        self.widget.show()
529        # Change the category index so we have a model available
530        category_index = self.widget.cbCategory.findText("Sphere")
531        self.widget.cbCategory.setCurrentIndex(category_index)
532
533        # Check the enablement/text
534        self.assertTrue(self.widget.cmdPlot.isEnabled())
535        self.assertEqual(self.widget.cmdPlot.text(), 'Calculate')
536
537        # Spying on plot update signal
538        spy = QtSignalSpy(self.widget, self.widget.communicate.plotRequestedSignal)
539
540        # Press Calculate
541        QtTest.QTest.mouseClick(self.widget.cmdPlot, QtCore.Qt.LeftButton)
542
543        # Observe cmdPlot caption change
544        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot')
545
546        # Make sure the signal has NOT been emitted
547        self.assertEqual(spy.count(), 0)
548
549        # Click again
550        QtTest.QTest.mouseClick(self.widget.cmdPlot, QtCore.Qt.LeftButton)
551
552        # This time, we got the update signal
553        self.assertEqual(spy.count(), 0)
554
555    def testPlotData(self):
556        """
557        See that data item can produce a chart
558        """
559        # By default, the compute/plot button is disabled
560        self.assertFalse(self.widget.cmdPlot.isEnabled())
561        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot')
562
563        self.widget.show()
564
565        # Set data
566        test_data = Data1D(x=[1,2], y=[1,2])
567
568        # Force same data into logic
569        self.widget.logic.data = test_data
570        self.widget.data_is_loaded = True
571
572        # Change the category index so we have a model available
573        category_index = self.widget.cbCategory.findText("Sphere")
574        self.widget.cbCategory.setCurrentIndex(category_index)
575
576        # Check the enablement/text
577        self.assertTrue(self.widget.cmdPlot.isEnabled())
578        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot')
579
580        # Spying on plot update signal
581        spy = QtSignalSpy(self.widget, self.widget.communicate.plotRequestedSignal)
582
583        # Press Calculate
584        QtTest.QTest.mouseClick(self.widget.cmdPlot, QtCore.Qt.LeftButton)
585
586        # Observe cmdPlot caption did not change
587        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot')
588
589        # Make sure the signal has been emitted == new plot
590        self.assertEqual(spy.count(), 1)
591
592    def testOnFit1D(self):
593        """
594        Test the threaded fitting call
595        """
596        # Set data
597        test_data = Data1D(x=[1,2], y=[1,2])
598        item = QtGui.QStandardItem()
599        updateModelItem(item, [test_data], "test")
600        # Force same data into logic
601        self.widget.data = item
602        category_index = self.widget.cbCategory.findText("Sphere")
603        self.widget.cbCategory.setCurrentIndex(category_index)
604
605        self.widget.show()
606
607        # Test no fitting params
608        self.widget.parameters_to_fit = []
609
610        with self.assertRaises(ValueError) as error:
611            self.widget.onFit()
612        self.assertEqual(str(error.exception), 'no fitting parameters')
613
614        # Assing fitting params
615        self.widget.parameters_to_fit = ['scale']
616
617        # Spying on status update signal
618        update_spy = QtSignalSpy(self.widget, self.widget.communicate.statusBarUpdateSignal)
619
620        with threads.deferToThread as MagicMock:
621            self.widget.onFit()
622            # thread called
623            self.assertTrue(threads.deferToThread.called)
624            # thread method is 'compute'
625            self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, 'compute')
626
627            # the fit button changed caption and got disabled
628            self.assertEqual(self.widget.cmdFit.text(), 'Running...')
629            self.assertFalse(self.widget.cmdFit.isEnabled())
630
631            # Signal pushed up
632            self.assertEqual(update_spy.count(), 1)
633
634    def testOnFit2D(self):
635        """
636        Test the threaded fitting call
637        """
638        # Set data
639        test_data = Data2D(image=[1.0, 2.0, 3.0],
640                           err_image=[0.01, 0.02, 0.03],
641                           qx_data=[0.1, 0.2, 0.3],
642                           qy_data=[0.1, 0.2, 0.3],
643                           xmin=0.1, xmax=0.3, ymin=0.1, ymax=0.3,
644                           mask=[True, True, True])
645
646        # Force same data into logic
647        item = QtGui.QStandardItem()
648        updateModelItem(item, [test_data], "test")
649        # Force same data into logic
650        self.widget.data = item
651        category_index = self.widget.cbCategory.findText("Sphere")
652        self.widget.cbCategory.setCurrentIndex(category_index)
653
654        self.widget.show()
655
656        # Test no fitting params
657        self.widget.parameters_to_fit = []
658
659        with self.assertRaises(ValueError) as error:
660            self.widget.onFit()
661        self.assertEqual(str(error.exception), 'no fitting parameters')
662
663        # Assing fitting params
664        self.widget.parameters_to_fit = ['scale']
665
666        # Spying on status update signal
667        update_spy = QtSignalSpy(self.widget, self.widget.communicate.statusBarUpdateSignal)
668
669        with threads.deferToThread as MagicMock:
670            self.widget.onFit()
671            # thread called
672            self.assertTrue(threads.deferToThread.called)
673            # thread method is 'compute'
674            self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, 'compute')
675
676            # the fit button changed caption and got disabled
677            self.assertEqual(self.widget.cmdFit.text(), 'Running...')
678            self.assertFalse(self.widget.cmdFit.isEnabled())
679
680            # Signal pushed up
681            self.assertEqual(update_spy.count(), 1)
682
683    def testOnHelp(self):
684        """
685        Test various help pages shown in this widget
686        """
687        #Mock the QWebView method
688        QtWebKit.QWebView.show = MagicMock()
689        QtWebKit.QWebView.load = MagicMock()
690
691        # Invoke the action on default tab
692        self.widget.onHelp()
693        # Check if show() got called
694        self.assertTrue(QtWebKit.QWebView.show.called)
695        # Assure the filename is correct
696        self.assertIn("fitting_help.html", QtWebKit.QWebView.load.call_args[0][0].toString())
697
698        # Change the tab to options
699        self.widget.tabFitting.setCurrentIndex(1)
700        self.widget.onHelp()
701        # Check if show() got called
702        self.assertEqual(QtWebKit.QWebView.show.call_count, 2)
703        # Assure the filename is correct
704        self.assertIn("residuals_help.html", QtWebKit.QWebView.load.call_args[0][0].toString())
705
706        # Change the tab to smearing
707        self.widget.tabFitting.setCurrentIndex(2)
708        self.widget.onHelp()
709        # Check if show() got called
710        self.assertEqual(QtWebKit.QWebView.show.call_count, 3)
711        # Assure the filename is correct
712        self.assertIn("sm_help.html", QtWebKit.QWebView.load.call_args[0][0].toString())
713
714        # Change the tab to poly
715        self.widget.tabFitting.setCurrentIndex(3)
716        self.widget.onHelp()
717        # Check if show() got called
718        self.assertEqual(QtWebKit.QWebView.show.call_count, 4)
719        # Assure the filename is correct
720        self.assertIn("pd_help.html", QtWebKit.QWebView.load.call_args[0][0].toString())
721
722        # Change the tab to magnetism
723        self.widget.tabFitting.setCurrentIndex(4)
724        self.widget.onHelp()
725        # Check if show() got called
726        self.assertEqual(QtWebKit.QWebView.show.call_count, 5)
727        # Assure the filename is correct
728        self.assertIn("mag_help.html", QtWebKit.QWebView.load.call_args[0][0].toString())
729
730    def testReadFitPage(self):
731        """
732        Read in the fitpage object and restore state
733        """
734        # Set data
735        test_data = Data1D(x=[1,2], y=[1,2])
736
737        # Force same data into logic
738        self.widget.logic.data = test_data
739        self.widget.data_is_loaded = True
740        category_index = self.widget.cbCategory.findText('Sphere')
741        self.widget.cbCategory.setCurrentIndex(category_index)
742        self.widget.parameters_to_fit = ['scale']
743        # Invoke the tested method
744        fp = self.widget.currentState()
745
746        # Prepare modified fit page
747        fp.current_model = 'onion'
748        fp.is_polydisperse = True
749
750        # Read in modified state
751        self.widget.readFitPage(fp)
752
753        # Check if the widget got updated accordingly
754        self.assertEqual(self.widget.cbModel.currentText(), 'onion')
755        self.assertTrue(self.widget.chkPolydispersity.isChecked())
756
757    def testCurrentState(self):
758        """
759        Set up the fitpage with current state
760        """
761        # Set data
762        test_data = Data1D(x=[1,2], y=[1,2])
763
764        # Force same data into logic
765        self.widget.logic.data = test_data
766        self.widget.data_is_loaded = True
767        category_index = self.widget.cbCategory.findText("Sphere")
768        self.widget.cbCategory.setCurrentIndex(category_index)
769        self.widget.parameters_to_fit = ['scale']
770
771        # Invoke the tested method
772        fp = self.widget.currentState()
773
774        # Test some entries. (Full testing of fp is done in FitPageTest)
775        self.assertIsInstance(fp.data, Data1D)
776        self.assertListEqual(list(fp.data.x), [1,2])
777        self.assertTrue(fp.data_is_loaded)
778        self.assertEqual(fp.current_category, "Sphere")
779        self.assertEqual(fp.current_model, "adsorbed_layer")
780        self.assertListEqual(fp.parameters_to_fit, ['scale'])
781
782    def testPushFitPage(self):
783        """
784        Push current state of fitpage onto stack
785        """
786        # Set data
787        test_data = Data1D(x=[1,2], y=[1,2])
788
789        # Force same data into logic
790        self.widget.logic.data = test_data
791        self.widget.data_is_loaded = True
792        category_index = self.widget.cbCategory.findText("Sphere")
793
794        # Asses the initial state of stack
795        self.assertEqual(self.widget.page_stack, [])
796
797        # Set the undo flag
798        self.widget.undo_supported = True
799        self.widget.cbCategory.setCurrentIndex(category_index)
800        self.widget.parameters_to_fit = ['scale']
801
802        # Check that the stack is updated
803        self.assertEqual(len(self.widget.page_stack), 1)
804
805        # Change another parameter
806        self.widget._model_model.item(2, 1).setText("3.0")
807        # Check that the stack is updated
808        self.assertEqual(len(self.widget.page_stack), 2)
809
810    def testPopFitPage(self):
811        """
812        Pop current state of fitpage from stack
813        """
814        # TODO: to be added when implementing UNDO/REDO
815        pass
816
817    def testOnMainPageChange(self):
818        """
819        Test update  values of modified parameters in models
820        """
821        # select model: cylinder / cylinder
822        category_index = self.widget.cbCategory.findText("Cylinder")
823        self.widget.cbCategory.setCurrentIndex(category_index)
824
825        model_index = self.widget.cbModel.findText("cylinder")
826        self.widget.cbModel.setCurrentIndex(model_index)
827
828        # modify the initial value of length (different from default)
829        # print self.widget.kernel_module.details['length']
830
831        new_value = "333.0"
832        self.widget._model_model.item(5, 1).setText(new_value)
833
834        # name of modified parameter
835        name_modified_param = str(self.widget._model_model.item(5, 0).text())
836
837        # check that the value has been modified in kernel_module
838        self.assertEqual(new_value,
839                         str(self.widget.kernel_module.params[name_modified_param]))
840
841        # check that range of variation for this parameter has NOT been changed
842        print self.widget.kernel_module.details[name_modified_param]
843        self.assertNotIn(new_value, self.widget.kernel_module.details[name_modified_param] )
844
845
846if __name__ == "__main__":
847    unittest.main()
Note: See TracBrowser for help on using the repository browser.