source: sasview/src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingOptionsTest.py @ 3a3f192

ESS_GUI_bumps_abstraction
Last change on this file since 3a3f192 was 3a3f192, checked in by ibressler, 5 years ago

FittingOptions?: adjusted tests to new implementation

  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[b0c5e8c]1import sys
2import unittest
[14ec91c5]3import webbrowser
[b0c5e8c]4
[53c771e]5from PyQt5 import QtGui, QtWidgets
[b0c5e8c]6
[7fb471d]7from unittest.mock import MagicMock
[b0c5e8c]8
9# set up import paths
10import path_prepare
11
12from UnitTesting.TestUtils import QtSignalSpy
13
14# Local
[3a3f192]15from sas.qtgui.Perspectives.Fitting.FittingOptions import \
16        FittingOptions, FittingMethod, FittingMethodParameter
[b0c5e8c]17
[53c771e]18if not QtWidgets.QApplication.instance():
19    app = QtWidgets.QApplication(sys.argv)
[b0c5e8c]20
21class FittingOptionsTest(unittest.TestCase):
22    '''Test the FittingOptions dialog'''
23    def setUp(self):
24        '''Create FittingOptions dialog'''
[3a3f192]25        self.widget = FittingOptions()
[b0c5e8c]26
27    def tearDown(self):
28        '''Destroy the GUI'''
29        self.widget.close()
30        self.widget = None
31
32    def testDefaults(self):
33        '''Test the GUI in its default state'''
[53c771e]34        self.assertIsInstance(self.widget, QtWidgets.QDialog)
[b0c5e8c]35        # Default title
[85487ebd]36        self.assertEqual(self.widget.windowTitle(), "Fit Algorithms")
[b0c5e8c]37
38        # The combo box
[53c771e]39        self.assertIsInstance(self.widget.cbAlgorithm, QtWidgets.QComboBox)
[3a3f192]40        self.assertTrue(self.widget.cbAlgorithm.count() >= 5) # at least the default bumps algos
[b0c5e8c]41        self.assertEqual(self.widget.cbAlgorithm.itemText(0), 'Nelder-Mead Simplex')
42        self.assertEqual(self.widget.cbAlgorithm.itemText(4), 'Levenberg-Marquardt')
43        self.assertEqual(self.widget.cbAlgorithm.currentIndex(), 4)
44
45    def testAssignValidators(self):
46        """
47        Check that line edits got correct validators
48        """
49        # Can't reliably test the method in action, but can easily check the results
50       
51        # DREAM
[3a3f192]52        self.widget.cbAlgorithm.setCurrentText("DREAM")
[b0c5e8c]53        self.assertIsInstance(self.widget.samples_dream.validator(), QtGui.QIntValidator)
54        self.assertIsInstance(self.widget.burn_dream.validator(), QtGui.QIntValidator)
55        self.assertIsInstance(self.widget.pop_dream.validator(), QtGui.QDoubleValidator)
56        self.assertIsInstance(self.widget.thin_dream.validator(), QtGui.QIntValidator)
57        self.assertIsInstance(self.widget.steps_dream.validator(), QtGui.QIntValidator)
58        # DE
[3a3f192]59        self.widget.cbAlgorithm.setCurrentText("Differential Evolution")
[b0c5e8c]60        self.assertIsInstance(self.widget.steps_de.validator(), QtGui.QIntValidator)
61        self.assertIsInstance(self.widget.CR_de.validator(), QtGui.QDoubleValidator)
62        self.assertIsInstance(self.widget.pop_de.validator(), QtGui.QDoubleValidator)
63        self.assertIsInstance(self.widget.F_de.validator(), QtGui.QDoubleValidator)
64        self.assertIsInstance(self.widget.ftol_de.validator(), QtGui.QDoubleValidator)
65        self.assertIsInstance(self.widget.xtol_de.validator(), QtGui.QDoubleValidator)
66
[72f4834]67        # bottom value for floats and ints
68        self.assertEqual(self.widget.steps_de.validator().bottom(), 0)
69        self.assertEqual(self.widget.CR_de.validator().bottom(), 0)
70
71        # Behaviour on empty cell
72        self.widget.onAlgorithmChange(3)
73        self.widget.steps_de.setText("")
74        # This should disable the OK button
[377ade1]75        ## self.assertFalse(self.widget.buttonBox.button(QtGui.QDialogButtonBox.Ok).isEnabled())
[72f4834]76        # Let's put some valid value in lineedit
77        self.widget.steps_de.setText("1")
78        # This should enable the OK button
[53c771e]79        self.assertTrue(self.widget.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).isEnabled())
[72f4834]80
[b0c5e8c]81    def testOnApply(self):
82        '''Test bumps update'''
83        # Spy on the update signal
84        spy_apply = QtSignalSpy(self.widget, self.widget.fit_option_changed)
85
86        # Set the DREAM optimizer
87        self.widget.cbAlgorithm.setCurrentIndex(2)
88        # Change some values
89        self.widget.init_dream.setCurrentIndex(2)
90        self.widget.steps_dream.setText("50")
91        # Apply the new values
92        self.widget.onApply()
93
94        self.assertEqual(spy_apply.count(), 1)
95        self.assertIn('DREAM', spy_apply.called()[0]['args'][0])
96
97        # Check the parameters
[3a3f192]98        self.assertEqual(self.widget.fittingMethods['DREAM'].params['steps'].value, 50.)
99        self.assertEqual(self.widget.fittingMethods['DREAM'].params['init'].value, 'cov')
[b0c5e8c]100
[53c771e]101    # test disabled until pyQt5 works well
[14ec91c5]102    def testOnHelp(self):
[b0c5e8c]103        ''' Test help display'''
[14ec91c5]104        webbrowser.open = MagicMock()
[b0c5e8c]105
106        # Invoke the action on default tab
107        self.widget.onHelp()
108        # Check if show() got called
[14ec91c5]109        self.assertTrue(webbrowser.open.called)
[b0c5e8c]110        # Assure the filename is correct
[14ec91c5]111        self.assertIn("optimizer.html", webbrowser.open.call_args[0][0])
[b0c5e8c]112
113        # Change the combo index
114        self.widget.cbAlgorithm.setCurrentIndex(2)
115        self.widget.onHelp()
116        # Check if show() got called
[14ec91c5]117        self.assertEqual(webbrowser.open.call_count, 2)
[b0c5e8c]118        # Assure the filename is correct
[14ec91c5]119        self.assertIn("fit-dream", webbrowser.open.call_args[0][0])
[b0c5e8c]120
121        # Change the index again
122        self.widget.cbAlgorithm.setCurrentIndex(4)
123        self.widget.onHelp()
124        # Check if show() got called
[14ec91c5]125        self.assertEqual(webbrowser.open.call_count, 3)
[b0c5e8c]126        # Assure the filename is correct
[14ec91c5]127        self.assertIn("fit-lm", webbrowser.open.call_args[0][0])
[b0c5e8c]128
[3a3f192]129    def testParamWidget(self):
[b0c5e8c]130        '''Test the helper function'''
131        # test empty call
[3a3f192]132        self.assertIsNone(self.widget.paramWidget(None, None))
[b0c5e8c]133        # test silly call
[3a3f192]134        self.assertIsNone(self.widget.paramWidget('poop', 'dsfsd'))
135        self.assertIsNone(self.widget.paramWidget(QtWidgets.QMainWindow(), None))
[b0c5e8c]136
137        # Switch to DREAM
[3a3f192]138        self.widget.cbAlgorithm.setCurrentText('DREAM')
139        fm = self.widget.fittingMethods['DREAM']
[b0c5e8c]140        # test smart call
[3a3f192]141        self.assertIsInstance(self.widget.paramWidget(fm, 'samples'), QtWidgets.QLineEdit)
142        self.assertIsInstance(self.widget.paramWidget(fm, 'init'), QtWidgets.QComboBox)
143
144    def testUpdateConfigFromWidget(self):
145        '''Test the config update'''
146        # test empty call
147        self.assertIsNone(self.widget.updateConfigFromWidget(None))
148        # test silly call
149        self.assertIsNone(self.widget.updateConfigFromWidget('poop'))
150        self.assertIsNone(self.widget.updateConfigFromWidget(QtWidgets.QMainWindow()))
[b0c5e8c]151
[3a3f192]152        # Switch to DREAM
153        self.widget.cbAlgorithm.setCurrentText('DREAM')
154        fm = FittingMethod("dream", "a long dream", [
155            FittingMethodParameter("samples", "# samples", int, 0),
156            FittingMethodParameter("init", "init func", int, 0)])
157        # test smart call
158        self.widget.updateConfigFromWidget(fm)
159        self.assertEqual(fm.params['samples'].value, 10000)
160        self.assertEqual(fm.params['init'].value, 'eps')
161
162    def testUpdateWidgetFromConfig(self):
[b0c5e8c]163        '''Test the widget update'''
[3a3f192]164        self.widget.cbAlgorithm.setCurrentText("Quasi-Newton BFGS")
[b0c5e8c]165        # modify some value
[3a3f192]166        self.assertEqual(self.widget.steps_newton.text(), '3000')
167        self.assertEqual(self.widget.starts_newton.text(), '1')
168        self.assertEqual(self.widget.ftol_newton.text(), '1e-06') # default
169        self.assertEqual(self.widget.xtol_newton.text(), '1e-12')
170        fm = self.widget.fittingMethods["Quasi-Newton BFGS"]
171        fm.params['steps'].value = 1234
172        fm.params['starts'].value = 666
173        fm.params['ftol'].value = 1e-6
174        fm.params['xtol'].value = 0.01
[b0c5e8c]175
176        # Invoke the method for the changed
[3a3f192]177        self.widget.updateWidgetFromConfig()
[b0c5e8c]178
179        # See that the widget picked up the right values
180        self.assertEqual(self.widget.steps_newton.text(), '1234')
181        self.assertEqual(self.widget.starts_newton.text(), '666')
182        self.assertEqual(self.widget.ftol_newton.text(), '1e-06') # default
183        self.assertEqual(self.widget.xtol_newton.text(), '0.01')
184
185if __name__ == "__main__":
186    unittest.main()
Note: See TracBrowser for help on using the repository browser.