diff options
Diffstat (limited to 'silx/gui/plot/test')
-rw-r--r-- | silx/gui/plot/test/__init__.py | 6 | ||||
-rw-r--r-- | silx/gui/plot/test/testColormap.py | 76 | ||||
-rw-r--r-- | silx/gui/plot/test/testColormapDialog.py | 321 | ||||
-rw-r--r-- | silx/gui/plot/test/testColors.py | 4 | ||||
-rw-r--r-- | silx/gui/plot/test/testComplexImageView.py | 4 | ||||
-rw-r--r-- | silx/gui/plot/test/testCurvesROIWidget.py | 19 | ||||
-rw-r--r-- | silx/gui/plot/test/testItem.py | 20 | ||||
-rw-r--r-- | silx/gui/plot/test/testMaskToolsWidget.py | 9 | ||||
-rw-r--r-- | silx/gui/plot/test/testPlotTools.py | 4 | ||||
-rw-r--r-- | silx/gui/plot/test/testPlotWidget.py | 22 | ||||
-rw-r--r-- | silx/gui/plot/test/testPlotWidgetNoBackend.py | 4 | ||||
-rw-r--r-- | silx/gui/plot/test/testProfile.py | 4 | ||||
-rw-r--r-- | silx/gui/plot/test/testSaveAction.py | 97 | ||||
-rw-r--r-- | silx/gui/plot/test/testScatterMaskToolsWidget.py | 9 | ||||
-rw-r--r-- | silx/gui/plot/test/testUtilsAxis.py | 23 | ||||
-rw-r--r-- | silx/gui/plot/test/utils.py | 127 |
16 files changed, 590 insertions, 159 deletions
diff --git a/silx/gui/plot/test/__init__.py b/silx/gui/plot/test/__init__.py index 07338b6..154a70a 100644 --- a/silx/gui/plot/test/__init__.py +++ b/silx/gui/plot/test/__init__.py @@ -24,7 +24,7 @@ # ###########################################################################*/ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "04/08/2017" +__date__ = "28/11/2017" import unittest @@ -52,6 +52,7 @@ from . import testUtilsAxis from . import testLimitConstraints from . import testComplexImageView from . import testImageView +from . import testSaveAction def suite(): @@ -79,5 +80,6 @@ def suite(): testUtilsAxis.suite(), testLimitConstraints.suite(), testComplexImageView.suite(), - testImageView.suite()]) + testImageView.suite(), + testSaveAction.suite()]) return test_suite diff --git a/silx/gui/plot/test/testColormap.py b/silx/gui/plot/test/testColormap.py index aa285d3..4888a7c 100644 --- a/silx/gui/plot/test/testColormap.py +++ b/silx/gui/plot/test/testColormap.py @@ -29,12 +29,14 @@ from __future__ import absolute_import __authors__ = ["H.Payno"] __license__ = "MIT" -__date__ = "05/12/2016" +__date__ = "17/01/2018" import unittest import numpy -from silx.test.utils import ParametricTestCase +from silx.utils.testutils import ParametricTestCase from silx.gui.plot.Colormap import Colormap +from silx.gui.plot.Colormap import preferredColormaps, setPreferredColormaps +from silx.utils.exceptions import NotEditableError class TestDictAPI(unittest.TestCase): @@ -134,14 +136,11 @@ class TestDictAPI(unittest.TestCase): 'autoscale': False } with self.assertRaises(ValueError): - colormapObject = Colormap._fromDict(clm_dict) + Colormap._fromDict(clm_dict) class TestObjectAPI(ParametricTestCase): """Test the new Object API of the colormap""" - def setUp(self): - signalHasBeenEmitting = False - def testVMinVMax(self): """Test getter and setter associated to vmin and vmax values""" vmin = 1.0 @@ -277,10 +276,73 @@ class TestObjectAPI(ParametricTestCase): self.assertEqual(image.shape[-1], 4) self.assertEqual(image.shape[:-1], data.shape) + def testGetNColors(self): + """Test getNColors method""" + # specific LUT + colormap = Colormap(name=None, + colors=((0, 0, 0), (1, 1, 1)), + vmin=1000, + vmax=2000) + colors = colormap.getNColors() + self.assertTrue(numpy.all(numpy.equal( + colors, + ((0, 0, 0, 255), (255, 255, 255, 255))))) + + def testEditableMode(self): + """Make sure the colormap will raise NotEditableError when try to + change a colormap not editable""" + colormap = Colormap() + colormap.setEditable(False) + with self.assertRaises(NotEditableError): + colormap.setVRange(0., 1.) + with self.assertRaises(NotEditableError): + colormap.setVMin(1.) + with self.assertRaises(NotEditableError): + colormap.setVMax(1.) + with self.assertRaises(NotEditableError): + colormap.setNormalization(Colormap.LOGARITHM) + with self.assertRaises(NotEditableError): + colormap.setName('magma') + with self.assertRaises(NotEditableError): + colormap.setColormapLUT(numpy.array([0, 1])) + with self.assertRaises(NotEditableError): + colormap._setFromDict(colormap._toDict()) + state = colormap.saveState() + with self.assertRaises(NotEditableError): + colormap.restoreState(state) + + +class TestPreferredColormaps(unittest.TestCase): + """Test get|setPreferredColormaps functions""" + + def setUp(self): + # Save preferred colormaps + self._colormaps = preferredColormaps() + + def tearDown(self): + # Restore saved preferred colormaps + setPreferredColormaps(self._colormaps) + + def test(self): + colormaps = 'viridis', 'magma' + + setPreferredColormaps(colormaps) + self.assertEqual(preferredColormaps(), colormaps) + + with self.assertRaises(ValueError): + setPreferredColormaps(()) + + with self.assertRaises(ValueError): + setPreferredColormaps(('This is not a colormap',)) + + colormaps = 'red', 'green' + setPreferredColormaps(('This is not a colormap',) + colormaps) + self.assertEqual(preferredColormaps(), colormaps) + def suite(): test_suite = unittest.TestSuite() - for ui in (TestDictAPI, TestObjectAPI): + for ui in (TestDictAPI, TestObjectAPI, TestPreferredColormaps): test_suite.addTest( unittest.defaultTestLoader.loadTestsFromTestCase(ui)) diff --git a/silx/gui/plot/test/testColormapDialog.py b/silx/gui/plot/test/testColormapDialog.py index d016548..8087369 100644 --- a/silx/gui/plot/test/testColormapDialog.py +++ b/silx/gui/plot/test/testColormapDialog.py @@ -1,7 +1,7 @@ # coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016 European Synchrotron Radiation Facility +# Copyright (c) 2016-2018 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,7 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "05/12/2016" +__date__ = "17/01/2018" import doctest @@ -35,6 +35,12 @@ import unittest from silx.gui.test.utils import qWaitForWindowExposedAndActivate from silx.gui import qt from silx.gui.plot import ColormapDialog +from silx.gui.test.utils import TestCaseQt +from silx.gui.plot.Colormap import Colormap, preferredColormaps +from silx.utils.testutils import ParametricTestCase +from silx.gui.plot.PlotWindow import PlotWindow + +import numpy.random # Makes sure a QApplication exists @@ -58,9 +64,320 @@ cmapDocTestSuite = doctest.DocTestSuite(ColormapDialog, tearDown=_tearDownQt) """Test suite of tests from the module's docstrings.""" +class TestColormapDialog(TestCaseQt, ParametricTestCase): + """Test the ColormapDialog.""" + def setUp(self): + TestCaseQt.setUp(self) + ParametricTestCase.setUp(self) + self.colormap = Colormap(name='gray', vmin=10.0, vmax=20.0, + normalization='linear') + + self.colormapDiag = ColormapDialog.ColormapDialog() + self.colormapDiag.setAttribute(qt.Qt.WA_DeleteOnClose) + + def tearDown(self): + del self.colormapDiag + ParametricTestCase.tearDown(self) + TestCaseQt.tearDown(self) + + def testGUIEdition(self): + """Make sure the colormap is correctly edited and also that the + modification are correctly updated if an other colormapdialog is + editing the same colormap""" + colormapDiag2 = ColormapDialog.ColormapDialog() + colormapDiag2.setColormap(self.colormap) + self.colormapDiag.setColormap(self.colormap) + + self.colormapDiag._comboBoxColormap.setCurrentName('red') + self.colormapDiag._normButtonLog.setChecked(True) + self.assertTrue(self.colormap.getName() == 'red') + self.assertTrue(self.colormapDiag.getColormap().getName() == 'red') + self.assertTrue(self.colormap.getNormalization() == 'log') + self.assertTrue(self.colormap.getVMin() == 10) + self.assertTrue(self.colormap.getVMax() == 20) + # checked second colormap dialog + self.assertTrue(colormapDiag2._comboBoxColormap.getCurrentName() == 'red') + self.assertTrue(colormapDiag2._normButtonLog.isChecked()) + self.assertTrue(int(colormapDiag2._minValue.getValue()) == 10) + self.assertTrue(int(colormapDiag2._maxValue.getValue()) == 20) + colormapDiag2.close() + + def testGUIModalOk(self): + """Make sure the colormap is modified if gone through accept""" + assert self.colormap.isAutoscale() is False + self.colormapDiag.setModal(True) + self.colormapDiag.show() + self.colormapDiag.setColormap(self.colormap) + self.assertTrue(self.colormap.getVMin() is not None) + self.colormapDiag._minValue.setValue(None) + self.assertTrue(self.colormap.getVMin() is None) + self.colormapDiag._maxValue.setValue(None) + self.mouseClick( + widget=self.colormapDiag._buttonsModal.button(qt.QDialogButtonBox.Ok), + button=qt.Qt.LeftButton + ) + self.assertTrue(self.colormap.getVMin() is None) + self.assertTrue(self.colormap.getVMax() is None) + self.assertTrue(self.colormap.isAutoscale() is True) + + def testGUIModalCancel(self): + """Make sure the colormap is not modified if gone through reject""" + assert self.colormap.isAutoscale() is False + self.colormapDiag.setModal(True) + self.colormapDiag.show() + self.colormapDiag.setColormap(self.colormap) + self.assertTrue(self.colormap.getVMin() is not None) + self.colormapDiag._minValue.setValue(None) + self.assertTrue(self.colormap.getVMin() is None) + self.mouseClick( + widget=self.colormapDiag._buttonsModal.button(qt.QDialogButtonBox.Cancel), + button=qt.Qt.LeftButton + ) + self.assertTrue(self.colormap.getVMin() is not None) + + def testGUIModalClose(self): + assert self.colormap.isAutoscale() is False + self.colormapDiag.setModal(False) + self.colormapDiag.show() + self.colormapDiag.setColormap(self.colormap) + self.assertTrue(self.colormap.getVMin() is not None) + self.colormapDiag._minValue.setValue(None) + self.assertTrue(self.colormap.getVMin() is None) + self.mouseClick( + widget=self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Close), + button=qt.Qt.LeftButton + ) + self.assertTrue(self.colormap.getVMin() is None) + + def testGUIModalReset(self): + assert self.colormap.isAutoscale() is False + self.colormapDiag.setModal(False) + self.colormapDiag.show() + self.colormapDiag.setColormap(self.colormap) + self.assertTrue(self.colormap.getVMin() is not None) + self.colormapDiag._minValue.setValue(None) + self.assertTrue(self.colormap.getVMin() is None) + self.mouseClick( + widget=self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Reset), + button=qt.Qt.LeftButton + ) + self.assertTrue(self.colormap.getVMin() is not None) + self.colormapDiag.close() + + def testGUIClose(self): + """Make sure the colormap is modify if go through reject""" + assert self.colormap.isAutoscale() is False + self.colormapDiag.show() + self.colormapDiag.setColormap(self.colormap) + self.assertTrue(self.colormap.getVMin() is not None) + self.colormapDiag._minValue.setValue(None) + self.assertTrue(self.colormap.getVMin() is None) + self.colormapDiag.close() + self.assertTrue(self.colormap.getVMin() is None) + + def testSetColormapIsCorrect(self): + """Make sure the interface fir the colormap when set a new colormap""" + self.colormap.setName('red') + for norm in (Colormap.NORMALIZATIONS): + for autoscale in (True, False): + if autoscale is True: + self.colormap.setVRange(None, None) + else: + self.colormap.setVRange(11, 101) + self.colormap.setNormalization(norm) + with self.subTest(colormap=self.colormap): + self.colormapDiag.setColormap(self.colormap) + self.assertTrue( + self.colormapDiag._normButtonLinear.isChecked() == (norm is Colormap.LINEAR)) + self.assertTrue( + self.colormapDiag._comboBoxColormap.getCurrentName() == 'red') + self.assertTrue( + self.colormapDiag._minValue.isAutoChecked() == autoscale) + self.assertTrue( + self.colormapDiag._maxValue.isAutoChecked() == autoscale) + if autoscale is False: + self.assertTrue(self.colormapDiag._minValue.getValue() == 11) + self.assertTrue(self.colormapDiag._maxValue.getValue() == 101) + self.assertTrue(self.colormapDiag._minValue.isEnabled()) + self.assertTrue(self.colormapDiag._maxValue.isEnabled()) + else: + self.assertFalse(self.colormapDiag._minValue._numVal.isEnabled()) + self.assertFalse(self.colormapDiag._maxValue._numVal.isEnabled()) + + def testColormapDel(self): + """Check behavior if the colormap has been deleted outside. For now + we make sure the colormap is still running and nothing more""" + self.colormapDiag.setColormap(self.colormap) + self.colormapDiag.show() + del self.colormap + self.assertTrue(self.colormapDiag.getColormap() is None) + self.colormapDiag._comboBoxColormap.setCurrentName('blue') + + def testColormapEditedOutside(self): + """Make sure the GUI is still up to date if the colormap is modified + outside""" + self.colormapDiag.setColormap(self.colormap) + self.colormapDiag.show() + + self.colormap.setName('red') + self.assertTrue( + self.colormapDiag._comboBoxColormap.getCurrentName() == 'red') + self.colormap.setNormalization(Colormap.LOGARITHM) + self.assertFalse(self.colormapDiag._normButtonLinear.isChecked()) + self.colormap.setVRange(11, 201) + self.assertTrue(self.colormapDiag._minValue.getValue() == 11) + self.assertTrue(self.colormapDiag._maxValue.getValue() == 201) + self.assertTrue(self.colormapDiag._minValue._numVal.isEnabled()) + self.assertTrue(self.colormapDiag._maxValue._numVal.isEnabled()) + self.assertFalse(self.colormapDiag._minValue.isAutoChecked()) + self.assertFalse(self.colormapDiag._maxValue.isAutoChecked()) + self.colormap.setVRange(None, None) + self.assertFalse(self.colormapDiag._minValue._numVal.isEnabled()) + self.assertFalse(self.colormapDiag._maxValue._numVal.isEnabled()) + self.assertTrue(self.colormapDiag._minValue.isAutoChecked()) + self.assertTrue(self.colormapDiag._maxValue.isAutoChecked()) + + def testSetColormapScenario(self): + """Test of a simple scenario of a colormap dialog editing several + colormap""" + colormap1 = Colormap(name='gray', vmin=10.0, vmax=20.0, + normalization='linear') + colormap2 = Colormap(name='red', vmin=10.0, vmax=20.0, + normalization='log') + colormap3 = Colormap(name='blue', vmin=None, vmax=None, + normalization='linear') + self.colormapDiag.setColormap(self.colormap) + self.colormapDiag.setColormap(colormap1) + del colormap1 + self.colormapDiag.setColormap(colormap2) + del colormap2 + self.colormapDiag.setColormap(colormap3) + del colormap3 + + def testNotPreferredColormap(self): + """Test that the colormapEditor is able to edit a colormap which is not + part of the 'prefered colormap' + """ + def getFirstNotPreferredColormap(): + cms = Colormap.getSupportedColormaps() + preferred = preferredColormaps() + for cm in cms: + if cm not in preferred: + return cm + return None + + colormapName = getFirstNotPreferredColormap() + assert colormapName is not None + colormap = Colormap(name=colormapName) + self.colormapDiag.setColormap(colormap) + self.colormapDiag.show() + cb = self.colormapDiag._comboBoxColormap + self.assertTrue(cb.getCurrentName() == colormapName) + cb.setCurrentIndex(0) + index = cb.findColormap(colormapName) + assert index is not 0 # if 0 then the rest of the test has no sense + cb.setCurrentIndex(index) + self.assertTrue(cb.getCurrentName() == colormapName) + + def testColormapEditableMode(self): + """Test that the colormapDialog is correctly updated when changing the + colormap editable status""" + colormap = Colormap(normalization='linear', vmin=1.0, vmax=10.0) + self.colormapDiag.setColormap(colormap) + for editable in (True, False): + with self.subTest(editable=editable): + colormap.setEditable(editable) + self.assertTrue( + self.colormapDiag._comboBoxColormap.isEnabled() is editable) + self.assertTrue( + self.colormapDiag._minValue.isEnabled() is editable) + self.assertTrue( + self.colormapDiag._maxValue.isEnabled() is editable) + self.assertTrue( + self.colormapDiag._normButtonLinear.isEnabled() is editable) + self.assertTrue( + self.colormapDiag._normButtonLog.isEnabled() is editable) + + # Make sure the reset button is also set to enable when edition mode is + # False + self.colormapDiag.setModal(False) + colormap.setEditable(True) + self.colormapDiag._normButtonLog.setChecked(True) + resetButton = self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Reset) + self.assertTrue(resetButton.isEnabled()) + colormap.setEditable(False) + self.assertFalse(resetButton.isEnabled()) + + +class TestColormapAction(TestCaseQt): + def setUp(self): + TestCaseQt.setUp(self) + self.plot = PlotWindow() + self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) + + self.colormap1 = Colormap(name='blue', vmin=0.0, vmax=1.0, + normalization='linear') + self.colormap2 = Colormap(name='red', vmin=10.0, vmax=100.0, + normalization='log') + self.defaultColormap = self.plot.getDefaultColormap() + + self.plot.getColormapAction()._actionTriggered(checked=True) + self.colormapDialog = self.plot.getColormapAction()._dialog + self.colormapDialog.setAttribute(qt.Qt.WA_DeleteOnClose) + + def tearDown(self): + self.colormapDialog.close() + self.plot.close() + del self.colormapDialog + del self.plot + TestCaseQt.tearDown(self) + + def testActiveColormap(self): + self.assertTrue(self.colormapDialog.getColormap() is self.defaultColormap) + + self.plot.addImage(data=numpy.random.rand(10, 10), legend='img1', + replace=False, origin=(0, 0), + colormap=self.colormap1) + self.plot.setActiveImage('img1') + self.assertTrue(self.colormapDialog.getColormap() is self.colormap1) + + self.plot.addImage(data=numpy.random.rand(10, 10), legend='img2', + replace=False, origin=(0, 0), + colormap=self.colormap2) + self.plot.addImage(data=numpy.random.rand(10, 10), legend='img3', + replace=False, origin=(0, 0)) + + self.plot.setActiveImage('img3') + self.assertTrue(self.colormapDialog.getColormap() is self.defaultColormap) + self.plot.getActiveImage().setColormap(self.colormap2) + self.assertTrue(self.colormapDialog.getColormap() is self.colormap2) + + self.plot.remove('img2') + self.plot.remove('img3') + self.plot.remove('img1') + self.assertTrue(self.colormapDialog.getColormap() is self.defaultColormap) + + def testShowHideColormapDialog(self): + self.plot.getColormapAction()._actionTriggered(checked=False) + self.assertFalse(self.plot.getColormapAction().isChecked()) + self.plot.getColormapAction()._actionTriggered(checked=True) + self.assertTrue(self.plot.getColormapAction().isChecked()) + self.plot.addImage(data=numpy.random.rand(10, 10), legend='img1', + replace=False, origin=(0, 0), + colormap=self.colormap1) + self.colormap1.setName('red') + self.plot.getColormapAction()._actionTriggered() + self.colormap1.setName('blue') + self.colormapDialog.close() + self.assertFalse(self.plot.getColormapAction().isChecked()) + + def suite(): test_suite = unittest.TestSuite() test_suite.addTest(cmapDocTestSuite) + for testClass in (TestColormapDialog, TestColormapAction): + test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase( + testClass)) return test_suite diff --git a/silx/gui/plot/test/testColors.py b/silx/gui/plot/test/testColors.py index 18f0902..4d617eb 100644 --- a/silx/gui/plot/test/testColors.py +++ b/silx/gui/plot/test/testColors.py @@ -26,13 +26,13 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "05/12/2016" +__date__ = "17/01/2018" import numpy import unittest -from silx.test.utils import ParametricTestCase +from silx.utils.testutils import ParametricTestCase from silx.gui.plot import Colors from silx.gui.plot.Colormap import Colormap diff --git a/silx/gui/plot/test/testComplexImageView.py b/silx/gui/plot/test/testComplexImageView.py index f8ec370..1933a95 100644 --- a/silx/gui/plot/test/testComplexImageView.py +++ b/silx/gui/plot/test/testComplexImageView.py @@ -26,14 +26,14 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "14/09/2017" +__date__ = "17/01/2018" import unittest import logging import numpy -from silx.test.utils import ParametricTestCase +from silx.utils.testutils import ParametricTestCase from silx.gui.plot import ComplexImageView from .utils import PlotWidgetTestCase diff --git a/silx/gui/plot/test/testCurvesROIWidget.py b/silx/gui/plot/test/testCurvesROIWidget.py index 716960a..0fd2456 100644 --- a/silx/gui/plot/test/testCurvesROIWidget.py +++ b/silx/gui/plot/test/testCurvesROIWidget.py @@ -1,7 +1,7 @@ # coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016 European Synchrotron Radiation Facility +# Copyright (c) 2016-2017 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -24,9 +24,9 @@ # ###########################################################################*/ """Basic tests for CurvesROIWidget""" -__authors__ = ["T. Vincent"] +__authors__ = ["T. Vincent", "P. Knobel"] __license__ = "MIT" -__date__ = "15/05/2017" +__date__ = "16/11/2017" import logging @@ -105,6 +105,19 @@ class TestCurvesROIWidget(TestCaseQt): del self.tmpFile + def testMiddleMarker(self): + """Test with middle marker enabled""" + self.widget.roiWidget.setMiddleROIMarkerFlag(True) + + # Add a ROI + self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) + + xleftMarker = self.plot._getMarker(legend='ROI min').getXPosition() + xMiddleMarker = self.plot._getMarker(legend='ROI middle').getXPosition() + xRightMarker = self.plot._getMarker(legend='ROI max').getXPosition() + self.assertAlmostEqual(xMiddleMarker, + xleftMarker + (xRightMarker - xleftMarker) / 2.) + def testCalculation(self): x = numpy.arange(100.) y = numpy.arange(100.) diff --git a/silx/gui/plot/test/testItem.py b/silx/gui/plot/test/testItem.py index 8c15bb7..1ba09c6 100644 --- a/silx/gui/plot/test/testItem.py +++ b/silx/gui/plot/test/testItem.py @@ -58,7 +58,7 @@ class TestSigItemChangedSignal(PlotWidgetTestCase): curve.setData(numpy.arange(100), numpy.arange(100)) # SymbolMixIn - curve.setSymbol('o') + curve.setSymbol('Circle') curve.setSymbol('d') curve.setSymbolSize(20) @@ -220,10 +220,28 @@ class TestSigItemChangedSignal(PlotWidgetTestCase): (ItemChangedType.DATA,)]) +class TestSymbol(PlotWidgetTestCase): + """Test item's symbol """ + + def test(self): + """Test sigItemChanged for curve""" + self.plot.addCurve(numpy.arange(10), numpy.arange(10), legend='test') + curve = self.plot.getCurve('test') + + # SymbolMixIn + curve.setSymbol('o') + name = curve.getSymbolName() + self.assertEqual('Circle', name) + + name = curve.getSymbolName('d') + self.assertEqual('Diamond', name) + + def suite(): test_suite = unittest.TestSuite() loadTests = unittest.defaultTestLoader.loadTestsFromTestCase test_suite.addTest(loadTests(TestSigItemChangedSignal)) + test_suite.addTest(loadTests(TestSymbol)) return test_suite diff --git a/silx/gui/plot/test/testMaskToolsWidget.py b/silx/gui/plot/test/testMaskToolsWidget.py index 191bbe0..40c1db3 100644 --- a/silx/gui/plot/test/testMaskToolsWidget.py +++ b/silx/gui/plot/test/testMaskToolsWidget.py @@ -26,7 +26,7 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "01/09/2017" +__date__ = "17/01/2018" import logging @@ -36,7 +36,8 @@ import unittest import numpy from silx.gui import qt -from silx.test.utils import temp_dir, ParametricTestCase +from silx.test.utils import temp_dir +from silx.utils.testutils import ParametricTestCase from silx.gui.test.utils import getQToolButtonFromAction from silx.gui.plot import PlotWindow, MaskToolsWidget from .utils import PlotWidgetTestCase @@ -84,8 +85,10 @@ class TestMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase): pos0 = xCenter, yCenter pos1 = xCenter + offset, yCenter + offset + self.mouseMove(plot, pos=(0, 0)) self.mouseMove(plot, pos=pos0) self.mousePress(plot, qt.Qt.LeftButton, pos=pos0) + self.mouseMove(plot, pos=(0, 0)) self.mouseMove(plot, pos=pos1) self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1) @@ -194,7 +197,7 @@ class TestMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase): self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) - self.maskWidget.pencilSpinBox.setValue(10) + self.maskWidget.pencilSpinBox.setValue(30) self.qapp.processEvents() # mask diff --git a/silx/gui/plot/test/testPlotTools.py b/silx/gui/plot/test/testPlotTools.py index a08a18a..3d5849f 100644 --- a/silx/gui/plot/test/testPlotTools.py +++ b/silx/gui/plot/test/testPlotTools.py @@ -26,13 +26,13 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "01/09/2017" +__date__ = "17/01/2018" import numpy import unittest -from silx.test.utils import ParametricTestCase, TestLogging +from silx.utils.testutils import ParametricTestCase, TestLogging from silx.gui.test.utils import ( qWaitForWindowExposedAndActivate, TestCaseQt, getQToolButtonFromAction) from silx.gui import qt diff --git a/silx/gui/plot/test/testPlotWidget.py b/silx/gui/plot/test/testPlotWidget.py index ccee428..72617e5 100644 --- a/silx/gui/plot/test/testPlotWidget.py +++ b/silx/gui/plot/test/testPlotWidget.py @@ -26,17 +26,17 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "01/09/2017" +__date__ = "26/01/2018" import unittest import logging import numpy -from silx.test.utils import ParametricTestCase +from silx.utils.testutils import ParametricTestCase from silx.gui.test.utils import SignalListener from silx.gui.test.utils import TestCaseQt -from silx.test import utils +from silx.utils import testutils from silx.utils import deprecation from silx.gui import qt @@ -77,9 +77,9 @@ class TestPlotWidget(PlotWidgetTestCase, ParametricTestCase): self.assertEqual(self.plot.getYAxis().getLabel(), ylabel) def _checkLimits(self, - expectedXLim=None, - expectedYLim=None, - expectedRatio=None): + expectedXLim=None, + expectedYLim=None, + expectedRatio=None): """Assert that limits are as expected""" xlim = self.plot.getXAxis().getLimits() ylim = self.plot.getYAxis().getLimits() @@ -132,13 +132,11 @@ class TestPlotWidget(PlotWidgetTestCase, ParametricTestCase): # Resize with aspect ratio self.plot.setKeepDataAspectRatio(True) - listener.clear() # Clean-up received signal self.qapp.processEvents() - self.assertEqual(listener.callCount(), 0) # No event when redrawing + listener.clear() # Clean-up received signal self.plot.resize(200, 200) self.qapp.processEvents() - self.assertNotEqual(listener.callCount(), 0) @@ -723,7 +721,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase): if getter is not None: self.assertEqual(getter(), expected) - @utils.test_logging(deprecation.depreclog.name, warning=2) + @testutils.test_logging(deprecation.depreclog.name, warning=2) def testOldPlotAxis_Logarithmic(self): """Test silx API prior to silx 0.6""" x = self.plot.getXAxis() @@ -762,7 +760,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase): self.assertEqual(self.plot.isYAxisLogarithmic(), False) self.assertEqual(listener.arguments(callIndex=-1), ("y", False)) - @utils.test_logging(deprecation.depreclog.name, warning=2) + @testutils.test_logging(deprecation.depreclog.name, warning=2) def testOldPlotAxis_AutoScale(self): """Test silx API prior to silx 0.6""" x = self.plot.getXAxis() @@ -801,7 +799,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase): self.assertEqual(self.plot.isYAxisAutoScale(), True) self.assertEqual(listener.arguments(callIndex=-1), ("y", True)) - @utils.test_logging(deprecation.depreclog.name, warning=1) + @testutils.test_logging(deprecation.depreclog.name, warning=1) def testOldPlotAxis_Inverted(self): """Test silx API prior to silx 0.6""" x = self.plot.getXAxis() diff --git a/silx/gui/plot/test/testPlotWidgetNoBackend.py b/silx/gui/plot/test/testPlotWidgetNoBackend.py index 3094a20..0d0ddc4 100644 --- a/silx/gui/plot/test/testPlotWidgetNoBackend.py +++ b/silx/gui/plot/test/testPlotWidgetNoBackend.py @@ -26,12 +26,12 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "27/06/2017" +__date__ = "17/01/2018" import unittest from functools import reduce -from silx.test.utils import ParametricTestCase +from silx.utils.testutils import ParametricTestCase import numpy diff --git a/silx/gui/plot/test/testProfile.py b/silx/gui/plot/test/testProfile.py index 43d3329..28d9669 100644 --- a/silx/gui/plot/test/testProfile.py +++ b/silx/gui/plot/test/testProfile.py @@ -26,12 +26,12 @@ __authors__ = ["T. Vincent", "P. Knobel"] __license__ = "MIT" -__date__ = "23/02/2017" +__date__ = "17/01/2018" import numpy import unittest -from silx.test.utils import ParametricTestCase +from silx.utils.testutils import ParametricTestCase from silx.gui.test.utils import ( TestCaseQt, getQToolButtonFromAction) from silx.gui import qt diff --git a/silx/gui/plot/test/testSaveAction.py b/silx/gui/plot/test/testSaveAction.py new file mode 100644 index 0000000..4dfe373 --- /dev/null +++ b/silx/gui/plot/test/testSaveAction.py @@ -0,0 +1,97 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ###########################################################################*/ +"""Test the plot's save action (consistency of output)""" + +__authors__ = ["P. Knobel"] +__license__ = "MIT" +__date__ = "28/11/2017" + + +import unittest +import tempfile +import os + +from silx.gui.plot import PlotWidget +from silx.gui.plot.actions.io import SaveAction + + +class TestSaveAction(unittest.TestCase): + + def setUp(self): + self.plot = PlotWidget(backend='none') + self.saveAction = SaveAction(plot=self.plot) + + self.tempdir = tempfile.mkdtemp() + self.out_fname = os.path.join(self.tempdir, "out.dat") + + def tearDown(self): + os.unlink(self.out_fname) + os.rmdir(self.tempdir) + + def testSaveMultipleCurvesAsSpec(self): + """Test that labels are properly used.""" + self.plot.setGraphXLabel("graph x label") + self.plot.setGraphYLabel("graph y label") + + self.plot.addCurve([0, 1], [1, 2], "curve with labels", + xlabel="curve0 X", ylabel="curve0 Y") + self.plot.addCurve([-1, 3], [-6, 2], "curve with X label", + xlabel="curve1 X") + self.plot.addCurve([-2, 0], [8, 12], "curve with Y label", + ylabel="curve2 Y") + self.plot.addCurve([3, 1], [7, 6], "curve with no labels") + + self.saveAction._saveCurves(self.out_fname, + SaveAction.ALL_CURVES_FILTERS[0]) # "All curves as SpecFile (*.dat)" + + with open(self.out_fname, "rb") as f: + file_content = f.read() + if hasattr(file_content, "decode"): + file_content = file_content.decode() + + # case with all curve labels specified + self.assertIn("#S 1 curve0 Y", file_content) + self.assertIn("#L curve0 X curve0 Y", file_content) + + # graph X&Y labels are used when no curve label is specified + self.assertIn("#S 2 graph y label", file_content) + self.assertIn("#L curve1 X graph y label", file_content) + + self.assertIn("#S 3 curve2 Y", file_content) + self.assertIn("#L graph x label curve2 Y", file_content) + + self.assertIn("#S 4 graph y label", file_content) + self.assertIn("#L graph x label graph y label", file_content) + + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest( + unittest.defaultTestLoader.loadTestsFromTestCase(TestSaveAction)) + return test_suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/silx/gui/plot/test/testScatterMaskToolsWidget.py b/silx/gui/plot/test/testScatterMaskToolsWidget.py index 178274a..0342c8f 100644 --- a/silx/gui/plot/test/testScatterMaskToolsWidget.py +++ b/silx/gui/plot/test/testScatterMaskToolsWidget.py @@ -26,7 +26,7 @@ __authors__ = ["T. Vincent", "P. Knobel"] __license__ = "MIT" -__date__ = "01/09/2017" +__date__ = "17/01/2018" import logging @@ -36,7 +36,8 @@ import unittest import numpy from silx.gui import qt -from silx.test.utils import temp_dir, ParametricTestCase +from silx.test.utils import temp_dir +from silx.utils.testutils import ParametricTestCase from silx.gui.test.utils import getQToolButtonFromAction from silx.gui.plot import PlotWindow, ScatterMaskToolsWidget from .utils import PlotWidgetTestCase @@ -86,8 +87,10 @@ class TestScatterMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase): pos0 = xCenter, yCenter pos1 = xCenter + offset, yCenter + offset + self.mouseMove(plot, pos=(0, 0)) self.mouseMove(plot, pos=pos0) self.mousePress(plot, qt.Qt.LeftButton, pos=pos0) + self.mouseMove(plot, pos=(0, 0)) self.mouseMove(plot, pos=pos1) self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1) @@ -197,7 +200,7 @@ class TestScatterMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase): self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) - self.maskWidget.pencilSpinBox.setValue(10) + self.maskWidget.pencilSpinBox.setValue(30) self.qapp.processEvents() # mask diff --git a/silx/gui/plot/test/testUtilsAxis.py b/silx/gui/plot/test/testUtilsAxis.py index 6702b00..3f19dcd 100644 --- a/silx/gui/plot/test/testUtilsAxis.py +++ b/silx/gui/plot/test/testUtilsAxis.py @@ -26,18 +26,20 @@ __authors__ = ["V. Valls"] __license__ = "MIT" -__date__ = "04/08/2017" +__date__ = "14/02/2018" import unittest from silx.gui.plot import PlotWidget +from silx.gui.test.utils import TestCaseQt from silx.gui.plot.utils.axis import SyncAxes -class TestAxisSync(unittest.TestCase): +class TestAxisSync(TestCaseQt): """Tests AxisSync class""" def setUp(self): + TestCaseQt.setUp(self) self.plot1 = PlotWidget() self.plot2 = PlotWidget() self.plot3 = PlotWidget() @@ -46,6 +48,7 @@ class TestAxisSync(unittest.TestCase): self.plot1 = None self.plot2 = None self.plot3 = None + TestCaseQt.tearDown(self) def testMoveFirstAxis(self): """Test synchronization after construction""" @@ -85,6 +88,22 @@ class TestAxisSync(unittest.TestCase): self.assertNotEqual(self.plot2.getXAxis().getLimits(), (10, 500)) self.assertNotEqual(self.plot3.getXAxis().getLimits(), (10, 500)) + def testAxisDestruction(self): + """Test synchronization when an axis disappear""" + _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()]) + + # Destroy the plot is possible + import weakref + plot = weakref.ref(self.plot2) + self.plot2 = None + result = self.qWaitForDestroy(plot) + if not result: + # We can't test + self.skipTest("Object not destroyed") + + self.plot1.getXAxis().setLimits(10, 500) + self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500)) + def testStop(self): """Test synchronization after calling stop""" sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()]) diff --git a/silx/gui/plot/test/utils.py b/silx/gui/plot/test/utils.py index ef547c6..ec9bc7c 100644 --- a/silx/gui/plot/test/utils.py +++ b/silx/gui/plot/test/utils.py @@ -26,17 +26,15 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "01/09/2017" +__date__ = "26/01/2018" import logging -import contextlib from silx.gui.test.utils import TestCaseQt from silx.gui import qt from silx.gui.plot import PlotWidget -from silx.gui.plot.backends.BackendMatplotlib import BackendMatplotlibQt logger = logging.getLogger(__name__) @@ -48,9 +46,10 @@ class PlotWidgetTestCase(TestCaseQt): plot attribute is the PlotWidget created for the test. """ + __screenshot_already_taken = False + def __init__(self, methodName='runTest'): TestCaseQt.__init__(self, methodName=methodName) - self.__mousePos = None def _createPlot(self): return PlotWidget() @@ -79,116 +78,16 @@ class PlotWidgetTestCase(TestCaseQt): logger.error("Plot is still alive") def tearDown(self): + if not self._currentTestSucceeded(): + # MPL is the only widget which uses the real system mouse. + # In case of a the windows is outside of the screen, minimzed, + # overlapped by a system popup, the MPL widget will not receive the + # mouse event. + # Taking a screenshot help debuging this cases in the continuous + # integration environement. + if not PlotWidgetTestCase.__screenshot_already_taken: + PlotWidgetTestCase.__screenshot_already_taken = True + self.logScreenShot() self.qapp.processEvents() self._waitForPlotClosed() super(PlotWidgetTestCase, self).tearDown() - - def _logMplEvents(self, event): - self.__mplEvents.append(event) - - @contextlib.contextmanager - def _waitForMplEvent(self, plot, mplEventType): - """Check if an event was received by the MPL backend. - - :param PlotWidget plot: A plot widget or a MPL plot backend - :param str mplEventType: MPL event type - :raises RuntimeError: When the event did not happen - """ - self.__mplEvents = [] - if isinstance(plot, BackendMatplotlibQt): - backend = plot - else: - backend = plot._backend - - callbackId = backend.mpl_connect(mplEventType, self._logMplEvents) - received = False - yield - for _ in range(100): - if len(self.__mplEvents) > 0: - received = True - break - self.qWait(10) - backend.mpl_disconnect(callbackId) - del self.__mplEvents - if not received: - self.logScreenShot() - raise RuntimeError("MPL event %s expected but nothing received" % mplEventType) - - def _haveMplEvent(self, widget, pos): - """Check if the widget at this position is a matplotlib widget.""" - if isinstance(pos, qt.QPoint): - pass - else: - pos = qt.QPoint(pos[0], pos[1]) - pos = widget.mapTo(widget.window(), pos) - target = widget.window().childAt(pos) - - # Check if the target is a MPL container - backend = target - if hasattr(target, "_backend"): - backend = target._backend - haveEvent = isinstance(backend, BackendMatplotlibQt) - return haveEvent - - def _patchPos(self, widget, pos): - """Return a real position relative to the widget. - - If pos is None, the returned value is the center of the widget, - as the default behaviour of functions like QTest.mouseMove. - Else the position is returned as it is. - """ - if pos is None: - pos = widget.size() / 2 - pos = pos.width(), pos.height() - return pos - - def _checkMouseMove(self, widget, pos): - """Returns true if the position differe from the current position of - the cursor""" - pos = qt.QPoint(pos[0], pos[1]) - pos = widget.mapTo(widget.window(), pos) - willMove = pos != self.__mousePos - self.__mousePos = pos - return willMove - - def mouseMove(self, widget, pos=None, delay=-1): - """Override TestCaseQt to wait while MPL did not reveive the expected - event""" - pos = self._patchPos(widget, pos) - willMove = self._checkMouseMove(widget, pos) - hadMplEvents = self._haveMplEvent(widget, self.__mousePos) - willHaveMplEvents = self._haveMplEvent(widget, pos) - if (not hadMplEvents and not willHaveMplEvents) or not willMove: - return TestCaseQt.mouseMove(self, widget, pos=pos, delay=delay) - with self._waitForMplEvent(widget, "motion_notify_event"): - TestCaseQt.mouseMove(self, widget, pos=pos, delay=delay) - - def mouseClick(self, widget, button, modifier=None, pos=None, delay=-1): - """Override TestCaseQt to wait while MPL did not reveive the expected - event""" - pos = self._patchPos(widget, pos) - self._checkMouseMove(widget, pos) - if not self._haveMplEvent(widget, pos): - return TestCaseQt.mouseClick(self, widget, button, modifier=modifier, pos=pos, delay=delay) - with self._waitForMplEvent(widget, "button_release_event"): - TestCaseQt.mouseClick(self, widget, button, modifier=modifier, pos=pos, delay=delay) - - def mousePress(self, widget, button, modifier=None, pos=None, delay=-1): - """Override TestCaseQt to wait while MPL did not reveive the expected - event""" - pos = self._patchPos(widget, pos) - self._checkMouseMove(widget, pos) - if not self._haveMplEvent(widget, pos): - return TestCaseQt.mousePress(self, widget, button, modifier=modifier, pos=pos, delay=delay) - with self._waitForMplEvent(widget, "button_press_event"): - TestCaseQt.mousePress(self, widget, button, modifier=modifier, pos=pos, delay=delay) - - def mouseRelease(self, widget, button, modifier=None, pos=None, delay=-1): - """Override TestCaseQt to wait while MPL did not reveive the expected - event""" - pos = self._patchPos(widget, pos) - self._checkMouseMove(widget, pos) - if not self._haveMplEvent(widget, pos): - return TestCaseQt.mouseRelease(self, widget, button, modifier=modifier, pos=pos, delay=delay) - with self._waitForMplEvent(widget, "button_release_event"): - TestCaseQt.mouseRelease(self, widget, button, modifier=modifier, pos=pos, delay=delay) |